Python中的C扩展-返回Py_BuildValue()内存泄漏问题 [英] C-extension in Python - return Py_BuildValue() memory leak problem

查看:730
本文介绍了Python中的C扩展-返回Py_BuildValue()内存泄漏问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个巨大的内存泄漏问题,涉及到我正在开发的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 AnotherIntVariablethat 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?

推荐答案

如果您查看Py_BuildValue的文档(

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆