答案是:“视情况而定;我们没有足够的代码来判断您的问题。”它取决于您告诉 Cython PyBuffer_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);
}
即内存正在分配但从未释放。如果你运行test() 并查看任务管理器,你可以看到内存使用率上升而不是返回。
或者,如果您告诉 Cython 它是一个 object,它可以让 Cython 像处理任何其他 Python 对象一样处理它,并正确管理引用计数:
# Good - no memory leak
cdef extern from "Python.h":
object PyBuffer_New(int size)
def test():
cdef int i
for i in range(100000):# call lots of times to allocate lots of memory
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;
}
注意DECREF,这将是释放对象的位置。如果您在此处运行test(),您不会看到内存使用量的长期跳跃。
可以通过将cdef 用于变量来在这两种情况之间跳转(例如在VideoFrame 的定义中)。如果他们使用PyObject* 而不小心DECREFs 那么他们可能正在泄漏内存......