Do I need to free memory returned from a C function called via CFFI?

落爺英雄遲暮 提交于 2020-01-02 07:53:48

问题


I have this example code that has a function text() returning a newly allocated string:

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)

This works fine:

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)

However, I could not find anything in the docs whether I actually need to manually free() the returned string of if CFFI takes ownership of the pointer as soon as it's returned to Python code.

Also, if I do need to manually free() it, do I need to expose free() in my cdefs or is does CFFI provide some nicer way for it?


回答1:


From the documentation on Working with pointers, structures and arrays, and quoting the correct section:

Any operation that would in C return a pointer or array or struct type gives you a fresh cdata object. Unlike the “original” one, these fresh cdata objects don’t have ownership

Therefore you must free it, there is no way it can assume the ownership: In C there are many functions that return a pointer to a constant string in memory, that not only it is not dynamically allocated, it is not allocated, or modifiable at all, for example. Freeing those would be very erroneous.


Also for free, the documentation says the following:

An alternative is to declare and call the C malloc() and free() functions, or some variant like mmap() and munmap(). Then you control exactly when the memory is allocated and freed. For example, add these two lines to your existing ffibuilder.cdef():

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

Since it is very important that the correct C standard library free is used for a pointer returned by strdup you cannot rely CFFI to magically do the correct thing, but instead as you suspected, you should expose free(). You can also use the gc as suggested by Barmar to register an automatic clean up, if needed:

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


来源:https://stackoverflow.com/questions/47080411/do-i-need-to-free-memory-returned-from-a-c-function-called-via-cffi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!