我使用SWIG编写用C ++编写的共享库的Java包装器。在库中有一个类似于此的联合:
union Union{
int f_int;
double f_double;
bool f_bool;
const char* f_string;
MyObject* f_my_object;
};
我将此联合包装起来,SWIG会为联盟中的所有字段生成getter和setter。
但是当我运行SWIG时,我收到了警告:
Warning 451: Setting a const char * variable may leak memory.
我理解为什么会这样,因为SWIG文档中有一个解释:http://www.swig.org/Doc1.3/SWIG.html(第5.5.4章)。
我的问题是:在包装const char *类型时是否有任何技巧可以避免内存泄漏。我必须处理这种类型,因为我无法对库源进行任何更改。
我会感谢你的帮助。
修改
我知道如何解决问题,但我不确定它是否正确。但是关于这个问题的第一个细节:
SWIG为const char * union成员setter生成C代码,如下所示:
SWIGEXPORT void JNICALL Java_example_exJNI_Union_1f_1string_1set(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
Union *arg1 = (Union *) 0 ;
char *arg2 = (char *) 0 ;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(Union **)&jarg1;
arg2 = 0;
if (jarg2) {
arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return ;
}
{
if (arg2) {
arg1->f_string = (char const *) (new char[strlen((const char *)arg2)+1]);
strcpy((char *)arg1->f_string, (const char *)arg2);
} else {
arg1->f_string = 0;
}
}
if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
}
问题在于:
arg1->f_string = (char const *) (new char[strlen((const char *)arg2)+1]);
正如SWIG文件所说:
当声明类型为const char *的变量时,SWIG仍会生成用于设置和获取值的函数。但是,默认行为不会释放先前的内容(导致可能的内存泄漏)。
所以我认为我应该强制SWIG生成如下所示的C代码:
SWIGEXPORT void JNICALL Java_example_exJNI_Union_1f_1string_1set(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
Union *arg1 = (Union *) 0 ;
static std::string* arg2_ = new std::string();
const char *arg2 = (const char *) 0 ;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(Union **)&jarg1;
arg2 = 0;
if (jarg2) {
arg2 = (const char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return ;
}
{
if (arg2) {
&(arg2_)->assign(arg2);
jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
arg1->f_string = arg2_->c_str();
} else {
arg1->f_string = 0;
}
}
}
是否解决了内存泄漏问题?我想是的,但也许我忽视了一些事情。
我想知道如何强制SWIG改变这个,只有这个功能看起来像我想要的那样。我应该使用某些类型图或其他东西吗?