我在Ubuntu中使用SWIG 2.0.10來調用Java中的C++代碼。SWIG java:釋放在C++中分配的內存
我的C++代碼是:
//ImgPro.h:
#include <vector>
typedef struct _bin
{
char* name;
float value;
} Bin;
typedef struct imgprops
{
std::vector<Bin> color;
int width;
int height;
char *print;
} ImageProperties;
class ImgPro
{
public:
ImgPro();
ImageProperties *processImage(char* imagePath);
};
的processImage來函數定義爲:
ImageProperties* ImgPro::processImage(char *imagePath)
{
ImageProperties* imgProp = new ImageProperties();
imgProp->width = 200;
imgProp->height = 200;
char* fp = new char(5);
strcpy(fp, "abc!");
imgProp->print = fp;
Bin outputBin1;
char *name1 = new char(strlen("red")+1);
strcpy(name1, "red");
outputBin1.name = name1;
outputBin1.value = 0.125;
Bin outputBin2;
char *name2 = new char(strlen("blue")+1);
strcpy(name2, "blue");
outputBin2.name = name1;
outputBin2.value = 0.27;
vector<Bin> tempVec;
tempVec.push_back(outputBin1);
tempVec.push_back(outputBin2);
imgProp->color = tempVec;
return imgProp;
}
因此,使用大口以產生JNI代碼,我使用了以下swig文件(注意:vector.i文件是使用這個example創建的):
%module CBIR
// to handle char** has String_Array in Java
%include <various.i>
%include "vector.i"
%{
#include "ImgPro.h"
%}
// to handle char** has String_Array in Java
%apply char **STRING_ARRAY { char ** };
// memory release
%extend imgprops {
~imgprops(){
if($self != NULL)
{
// releasing print element
if($self->print != NULL)
delete[] $self->print;
// releasing vector elements
for(uint x = 0; x < $self->color.size(); x++)
{
Bin currentBin = $self->color[x];
if(currentBin.name != NULL)
delete[] currentBin.name;
}
// releasing stuct Pointer
delete $self;
}
}
}
%include "ImgPro.h"
%template(BinVec) std::vector<Bin>;
這產生在swig_wrap文件的下一個功能:
SWIGINTERN void delete_imgprops(imgprops *self){
if(self != NULL)
{
// releasing print element
if(self->print != NULL)
delete[] self->print;
// releasing vector elements
for(uint x = 0; x < self->color.size(); x++)
{
Bin currentBin = self->color[x];
if(currentBin.name != NULL)
delete[] currentBin.name;
}
// releasing stuct Pointer
delete self;
}
}
被稱爲在刪除ImageProperties C++函數。
但是,在運行中的Java下面的代碼永遠不會釋放內存(調用該函數delete_imgprops)在C++中進行分配:
ImgPro imgObject = new ImgPro();
ImageProperties propObject = imgObject.processImage("imagem123-jpg");
int width = propObject.getWidth();
int height = propObject.getHeight();
String fingerPrint = propObject.getPrint();
propObject.delete();
imgObject.delete();
因此,分析代碼流之後,我找到了原因爲什麼內存ISN」 t發佈。通過SWIG生成的ImageProperties.Java文件包含,除其他外,刪除功能:
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
CBIRJNI.delete_ImageProperties(swigCPtr);
}
swigCPtr = 0;
}
}
線 「CBIRJNI.delete_ImageProperties(swigCPtr);」永遠不會調用,因爲var swigCMemOwn總是爲false。
據我所知,因爲Java方面沒有分配內存,所以它也沒有釋放它,所以我能做些什麼來確保java釋放內存,而不對swig生成的java文件進行任何修改?
我發現釋放內存的解決方案是對delete()函數的if(swigCMemOwn)測試發表評論,但我不認爲這是做這件事的最好方法!
感謝,塞爾吉奧
我打電話只是在測試階段手動刪除(),看看內存被釋放或沒有(因爲在這個測試階段,我有一個小程序存在於垃圾收集器的調用之前)。 但我主要懷疑我應該在swig文件(甚至在C++實現)中更改哪些內容,以確保內存在delete()方法上發佈而不做任何修改。 – Sergio
該文檔實際上說:「*理想*你不需要調用delete()」。儘管你的Java包裝在垃圾收集時會爲你調用delete(),但是要注意,這隻會在最後一個引用被釋放後纔會發生*和*垃圾收集循環運行 - 這可能永遠不會發生!如果在完成對象後立即運行C++析構函數非常重要,則需要手動調用delete()。當你的C++類使用RAII風格的資源管理,或者當他們擁有JVM看不到的大塊C++堆時。 – jcl