SWIGjava:释放C++中分配的内存
我在Ubuntu中使用SWI2.2.10调用java中的C++代码。p> <>我的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;
}
因此,为了使用swig生成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;
}
}
在删除IVIEWECTRANCE C++函数中调用。
但是,在Java中运行以下代码不会释放C++中分配的内存(调用函数delete_imgprops):
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();
所以,在分析了代码流之后,我找到了内存没有释放的原因。ImageProperties。SWIG生成的Java文件包括删除功能:
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
CBIRJNI.delete_ImageProperties(swigCPtr);
}
swigCPtr = 0;
}
}
行“CBIRJNI.delete_ImageProperties(swigCPtr);”从未调用,因为var swigcmomewn始终为false
我理解这一点,因为Java端不分配内存,所以它也不会释放内存,所以我可以做些什么来确保Java在不修改swig生成的Java文件的情况下释放内存
我发现释放内存的解决方案是对delete()函数的if(swigcmomewn)测试进行注释,但我认为这不是最好的方法
谢谢,塞尔吉奥
# 1 楼答案
你不应该手动调用
delete()
。如果您正确地实现了C++析构函数(或在任何地方释放内存),只要java包装对象被释放,内存就会被释放,SWIG包装代码将自动调用适当的方法。更多信息请访问SWIG doc for Java# 2 楼答案
你可以看看
指令(在swig 2.0中)使用工厂方法。它告诉SWIG,一个特定的函数将返回一个新的对象,java代理类也应该负责清理C++内存。生成的代码将设置SigigcMeMoto为true,导致C++析构函数被调用。
如果你自己调用delete方法,那没关系——你只需要改变编程风格,把swig'ed对象看作是一个文件句柄或数据库连接。完成后,您可以对这些对象调用close(),因为您不想等待java的GC在稍后的某个未知点启动并收集这个昂贵的资源——您需要手动管理它
但显然,您还必须记住执行良好的代码规则,以确保在调用delete()之后,不会在任何地方使用java对象