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

时间:2017-11-02 16:40:46

标签: python c memory-management free 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)

这很好用:

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)

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

另外,如果我确实需要手动free(),我是否需要在 cdefs 中公开free(),或者CFFI是否为它提供了一些更好的方法?< / p>

1 个答案:

答案 0 :(得分:5)

Working with pointers, structures and arrays上的文档和引用正确的部分

  

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

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

同样适用于free,文档说明如下:

  

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

void *malloc(size_t size);
void free(void *ptr);

由于正确 C标准库free用于strdup返回的指针非常重要,因此您无法依靠CFFI神奇地做正确的事情,相反,如您所怀疑,您应该公开free()。如果需要,您还可以使用Barmar建议的gc注册自动清理:

x = ffi.gc(x, lib.free)