Memory leaks PyBuffer_New:我需要手动释放吗?

Memory leaks PyBuffer_New:我需要手动释放吗?,memory-leaks,cython,pybuffer,Memory Leaks,Cython,Pybuffer,我正在搜索其他人代码中的内存泄漏。我发现: def current(self): ... data = PyBuffer_New(buflen) PyObject_AsCharBuffer(data, &data_ptr, &buflen) ... return VideoFrame(data, self.frame_size, self.frame_mode, timestamp=<dou

我正在搜索其他人代码中的内存泄漏。我发现:

def current(self):
    ...
    data = PyBuffer_New(buflen)
    PyObject_AsCharBuffer(data, &data_ptr, &buflen)
    ...
    return VideoFrame(data, self.frame_size, self.frame_mode,
                      timestamp=<double>self.frame.pts/<double>AV_TIME_BASE,
                      frameno=self.frame.display_picture_number)


cdef class VideoFrame:
    def __init__(self, data, size, mode, timestamp=0, frameno=0):
        self.data = data
        ...
def当前(自身):
...
数据=PyBuffer_新(buflen)
PyObject_AsCharBuffer(数据和数据_ptr及buflen)
...
返回视频帧(数据、自帧大小、自帧模式、,
时间戳=self.frame.pts/AV_TIME_BASE,
frameno=self.frame.display\u picture\u number)
cdef级视频帧:
def u uu init u uuuu(自身、数据、大小、模式、时间戳=0、帧号=0):
self.data=数据
...
函数中的
current()
不是免费的
或类似功能,在
视频帧中也不是。当
VideoFrame
对象被删除时,
PyBuffer
是否自动释放?

答案是:“视情况而定;我们没有足够的代码从您的问题中辨别出来。”这取决于您告诉Cython
PyBuffer\u New
返回的类型。我将给出两个简单的例子,希望你能为你更复杂的例子解决这个问题

如果您告诉Cython它是一个
PyObject*
,它对该类型没有天生的知识,也不会做任何事情来跟踪内存:

# BAD - memory leak!

cdef extern from "Python.h":
    ctypedef struct PyObject
    PyObject* PyBuffer_New(int size)

def test():
    cdef int i
    for i in range(100000): # call lots of times to allocate lots of memory
        # (type of a is automatically inferred to be PyObject*
        # to match the function definition)
        a = PyBuffer_New(1000)
生成的循环代码大致如下所示:

for (__pyx_t_1 = 0; __pyx_t_1 < 1000; __pyx_t_1+=1) {
  __pyx_v_i = __pyx_t_1;
  __pyx_v_a = PyBuffer_New(1000);
}
然后生成循环的代码

for (__pyx_t_1 = 0; __pyx_t_1 < 100000; __pyx_t_1+=1) {
  __pyx_v_i = __pyx_t_1;
  __pyx_t_2 = PyBuffer_New(1000); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_a, __pyx_t_2);
    __pyx_t_2 = 0;
}
(\uuuuPyx\uT\u1=0;\uuuPyx\uT\u1<100000;\uuuuPyx\uT\u1+=1)的
{
__pyx_v_i=u pyx_t_1;
__pyx_t_2=PyBuffer_New(1000);如果(不太可能(!_pyx_t_2)){uuu pyx_文件名=u pyx_f[0];u pyx_lineno=7;u pyx_clineno=u线条uu;goto_uPyx_L1_错误;}
__Pyx_GOTREF(uu Pyx_t_2);
__Pyx_XDECREF_集(uu Pyx_v_a,uu Pyx_t_2);
__pyx_t_2=0;
}
请注意
DECREF
,这将是解除分配对象的位置。如果在此处运行
test()
,则不会看到内存使用量的长期跳跃


通过对变量使用
cdef
(例如在
VideoFrame
的定义中),可以在这两种情况之间跳转。如果他们使用
PyObject*
时没有小心地
DECREF
s,那么他们可能正在泄漏内存…

谢谢!似乎作者已经实现了“正确的”
objectpybuffer\u New(int-size)
方式。我还看到在
VideoFrame
data
中定义为
cdef只读对象数据。这就是它可能泄漏的情况吗?刚刚发现
\uuupyx\ugotref(\uuuupyx\ut\u2)PyBuffer\u New
之后调用code>。所以我想一切都是正确实现的。@P.R.我看不到任何我立即怀疑的东西(包括
VideoFrame.data
)。虽然很明显很难从中分辨出来。查找内存泄漏的首选工具(至少在Linux上)是Valgrind。我已经有一段时间没有真正使用它了,所以我不能给出任何真正的建议。
for (__pyx_t_1 = 0; __pyx_t_1 < 100000; __pyx_t_1+=1) {
  __pyx_v_i = __pyx_t_1;
  __pyx_t_2 = PyBuffer_New(1000); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_a, __pyx_t_2);
    __pyx_t_2 = 0;
}