gpt4 book ai didi

java - SWIG java : releasing memory allocated in c++

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:46:48 24 4
gpt4 key购买 nike

我在 Ubuntu 中使用 SWIG 2.0.10 来调用 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;

因此,为了使用 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;
}
}

在 delete ImageProperties 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();

于是,通过分析代码流程,找到了内存没有释放的原因。 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 始终为假。

我了解到,因为 Java 端不分配内存,所以它也不释放它,那么我该怎么做才能确保 java 释放内存而不对 swig 生成的 java 文件进行任何修改?

我发现释放内存的解决方案是在 delete() 函数上注释 if(swigCMemOwn) 测试,但我认为这不是最好的方法!

谢谢,塞尔吉奥

最佳答案

你可以看看

%newobject

带有工厂方法的指令(在 swig 2.0 中)。它告诉 swig,一个特定的函数将返回一个新对象,并且 java 代理类也应该负责清理 c++ 内存。生成的代码会将 swigCMemOwn 设置为 true,从而导致调用 c++ 析构函数。

如果您确实自己调用了 delete 方法,那很好 - 您只需改变您的编程风格,将 swig'ed 对象视为类似于文件句柄或数据库连接的东西。完成后,您会在这些对象上调用 close(),因为您不想等待 Java 的 GC 在以后某个未知的时间点启动并收集这种昂贵的资源 - 您希望手动管理它。

但是您显然还必须记住遵守良好的代码纪律,以确保在调用 delete() 后不会在任何地方使用 java 对象

关于java - SWIG java : releasing memory allocated in c++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21068884/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com