Python中的C扩展-返回Py_BuildValue()内存泄漏问题 [英] C-extension in Python - return Py_BuildValue() memory leak problem
问题描述
我遇到了一个巨大的内存泄漏问题,涉及到我正在开发的C扩展名.在C语言中,我有一个名为A
的双精度数组和一个我想传递给Python的名为AnotherIntVariable
的int变量.好吧,在我的C扩展模块中,我执行以下操作:
I have a huge memory leak problem involving a C-extension I'm developing. In C, I have an array of doubles called A
and an int variable called AnotherIntVariable
that I want to pass to Python. Well, in my C-extension module I do the following:
int i;
PyObject *lst = PyList_New(len_A);
PyObject *num;
if(!lst)
return NULL;
for(i=0;i<len_A;i++){
num=PyFloat_FromDouble(A[i]);
if(!num){
Py_DECREF(lst);
return NuLL;
}
PyList_SET_ITEM(lst,i,num);
}
free(A);
return Py_BuildValue("Oi",lst,AnotherIntVariable)
因此在Python中,我会收到此列表和类似这样的int:
So in Python i recieve this list and the int like this:
Pyt_A,Pyt_int=MyCModule.MyCFunction(...)
其中Pyt_A和Pyt_int是列表和我从C扩展名"MyCModule
"以及我先前介绍的函数"MyCFunction
"获得的整数.
Where Pyt_A and Pyt_int are the list and the integer I get from my C-extension "MyCModule
", from the function "MyCFunction
" that I described earlier.
问题在于,在Python中,我使用此Pyt_A
数组(因此,为什么我使用Py_BuildValue
而不是简单的return
语句来执行INCREF,以便从垃圾收集器),但随后我需要以某种方式取消引用它才能释放分配的内存.问题是我多次使用MyCFunction
函数,这会导致内存泄漏,因为我不知道如何取消引用在python中获得的数组以摆脱它.
The problem is that, in Python, I use this Pyt_A
array (so that's why I use Py_BuildValue
instead of a simple return
statement, to do an INCREF in order to save this variable for a moment from the garbage collector) but then I need to dereference it somehow in order to free that allocated memory. The problem is that I use the MyCFunction
function several times, and this produces a memory leakage because I don't know how to dereference the array that I get in python in order to get rid of it.
我尝试通过在代码的C部分执行return lst
而不是Py_BuildValue("Oi",lst,AnotherIntVariable)
来返回数组,但是当我尝试在python中使用它时,只会导致分段错误(可能是因为垃圾收藏家做了他的工作)...
I tried just returning the array by doing a return lst
in the C part of the code instead of the Py_BuildValue("Oi",lst,AnotherIntVariable)
, but that only results in a Segmentation Fault when I try to use it in python (probably because the garbage collector did his work)...
...我在这里想念什么?有人可以帮我吗?
...what am I missing here? Can anybody help me?
推荐答案
If you look at the documentation for Py_BuildValue
(http://docs.python.org/3/c-api/arg.html#c.Py_BuildValue) you can see that under the O
typecode, it says that the reference count of the passed in object is incremented by one (Note: an earlier section in that page describes the O
typecode for PyArg_ParseTuple
, which doesn't increment the reference count, but also isn't relevant here).
因此,在调用Py_BuildValue
之后,列表的引用计数为2
,但是您只希望它为1
.
So, after the call to Py_BuildValue
, the refcount for your list is 2
, but you only want it to be 1
.
代替直接返回Py_BuildValue
的结果,将其保存到PyObject
指针,减少lst
引用计数,然后返回结果.
Instead of returning the result of Py_BuildValue
directly, save it to a PyObject
pointer, decrement the lst
reference count, then return your result.
无论如何,您应该检查Py_BuildValue
调用的结果,因为如果Py_BuildValue
失败(即返回NULL
),您还需要释放num
.
You should be checking the result of the Py_BuildValue
call anyway, since you also need to free num
in the event that Py_BuildValue
fails (i.e. returns NULL
).
这篇关于Python中的C扩展-返回Py_BuildValue()内存泄漏问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!