我是否需要释放通过CFFI调用的C函数返回的内存?

Thi*_*ter 3 c python free memory-management python-cffi

我有一个示例代码,该示例代码具有一个text()返回新分配的字符串的函数:

ffi_test = FFI()
ffi_test.set_source('_test', '''
char* test() { return strdup("hello world"); }
''')
ffi_test.cdef('''
char* test();
void free(void *);
''')
ffi_test.compile(verbose=True)
Run Code Online (Sandbox Code Playgroud)

这很好用:

In [1]: from _test import ffi, lib
In [2]: x = lib.test()
In [3]: ffi.string(x)
Out[3]: b'hello world'
In [4]: lib.free(x)
Run Code Online (Sandbox Code Playgroud)

但是,我在文档中找不到任何内容,是否我真的需要手动free()返回的字符串,如果CFFI在返回到Python代码后立即拥有该指针的所有权。

另外,如果我确实需要手动执行free()此操作,是否需要free()cdef中公开它?CFFI是否为此提供了更好的方法?

Ant*_*ala 5

从有关使用指针,结构和数组的文档中,并引用正确的部分

在C中将返回指针,数组或结构类型的任何操作都会为您提供一个新鲜的cdata对象。与“原始”对象不同,这些新的cdata对象没有所有权

因此,您必须释放它,它无法假定所有权:在C中,有许多函数返回指向内存中常量字符串的指针,不仅它不是动态分配的,它也不是分配的,或者在以下位置可修改的:例如。释放这些将是非常错误的。


同样对于free,文档说以下内容:

另一种选择是声明并调用C malloc()和free()函数,或某些变体,例如mmap()和munmap()。然后,您可以精确控制何时分配和释放内存。例如,将这两行添加到现有的ffibuilder.cdef()中:

void *malloc(size_t size);
void free(void *ptr);
Run Code Online (Sandbox Code Playgroud)

由于将正确的 C标准库free用于由strdup您返回的指针非常重要,因此您不能依靠CFFI神奇地执行正确的操作,而应该怀疑,您应该公开free()gc如果需要,您还可以使用Barmar建议的来注册自动清除:

x = ffi.gc(x, lib.free)
Run Code Online (Sandbox Code Playgroud)