c++到python的swig导致内存泄漏!与Py_BuildValue和SWIG_NewPointerObj相关
我有一段Swig代码,导致了内存泄漏。
PyObject* FindBestMatch(const Bar& fp) {
Foo* ptr(new Foo());
float match;
// call a function to fill the foo pointer
return Py_BuildValue(
"(fO)",
match,
SWIG_NewPointerObj(ptr,
SWIGTYPE_p_Foo,
0 /* own */));
}
我发现ptr没有被正确释放。所以我做了以下修改:
PyObject* FindBestMatch(const Bar& fp) {
Foo* ptr(new Foo());
float match;
// call a function to fill the foo pointer
*PyObject *o = SWIG_NewPointerObj(ptr,
SWIGTYPE_p_Foo,
1 /* own */);* <------- 1 means pass the ownership to python
PyObject *result = Py_BuildValue("(fO)", match, o);
Py_XDECREF(o);
return result;
}
但我不太确定这样做会不会导致内存损坏。在这里,Py_XDECREF(o)会减少引用计数,这样可以释放对象“o”占用的内存。但是o是返回值“result”的一部分。释放“o”可能会导致数据损坏,我猜?
我试了我的修改,效果很好,调用者(Python代码)也看到了预期的数据。但这可能是因为没有其他人覆盖那个内存区域。
那么,处理上面代码的内存管理的正确方法是什么呢?我查了Swig的文档,但没有看到很具体的描述。
请帮帮我!
谢谢,
xin
1 个回答
0
根据SWIG自动生成的代码,对于分配新对象的函数,正确的做法是把Python的所有权标志设置为1,这意味着:这个指针归Python所有
这样说是有道理的:你的new Foo()
对象在哪里被释放呢?SWIG的包装对象会处理这个问题。
PyObject* FindBestMatch(const Bar& fp) {
Foo* ptr(new Foo());
float match;
// call a function to fill the foo pointer
PyObject* o = SWIG_NewPointerObj(ptr,
SWIGTYPE_p_Foo,
SWIG_BUILTIN_INIT | 0);
PyObject* result = Py_BuildValue("(fO)", match, o);
return result;
}
不过,我不明白为什么要减少o的引用计数:如果我没记错的话,当把一个对象传给元组或列表时,引用是被“偷走”的。