2017-11-02 6 views
1

Ich habe dieses Beispiel-Code, der eine Funktion text() Zurückgeben eines neu zugewiesenen String hat:Muss ich den von einer über CFFI aufgerufenen C-Funktion zurückgegebenen Speicher freigeben?

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) 

Dies funktioniert:

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) 

Allerdings konnte ich nichts in der Dokumentation, ob ich wirklich brauchen zu manuell free() die zurückgegebene Zeichenfolge von, wenn CFFI Besitz des Zeigers übernimmt, sobald es an Python-Code zurückgegeben wird.

Auch, wenn ich brauche, um manuell free() es, ich free() in meinem cdefs aussetzen müssen oder nicht CFFI etwas schönere Art und Weise für sie zur Verfügung stellen?

+0

Wenn „Besitz“ eines Objekts von einer Softwarekomponente zur anderen weitergegeben wird, wird der neue Eigentümer für die Freigabe zuständige Erinnerung. Weil * das ist, was "Besitz" bedeutet. * – kindall

Antwort

3

Aus der Dokumentation auf Working with pointers, structures and arrays und unter Angabe den richtigen Abschnitt:

Jede Operation, die in C einen Zeiger oder Array oder Struktur-Typ gibt Ihnen ein frisches cdata Objekt würde. Anders als die „Original“ ein, diese frische cdata Objekte haben kein Eigentum

Deshalb ist es befreien Sie müssen, gibt es keine Möglichkeit, es den Besitz übernehmen kann: In C gibt es viele Funktionen, die eine Rückkehr Zeiger auf eine Konstante Zeichenfolge im Speicher, die nicht nur nicht dynamisch zugeordnet ist, ist es zum Beispiel nicht zugeordnet oder überhaupt änderbar. Das zu befreien wäre sehr falsch.


Auch für free, sagt die Dokumentation folgendes:

Eine Alternative ist die C malloc zu erklären, und rufen Sie() und free() Funktionen, oder eine Variante wie mmap() und munmap(). Dann steuern Sie genau, wann der Speicher zugewiesen und freigegeben wird. Fügen Sie zum Beispiel diese beiden Zeilen zu Ihrem bestehenden ffibuilder.cdef():

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

Da es sehr wichtig ist, dass die richtige C-Standardbibliothek free für einen Zeiger von strdup zurück verwendet wird Sie nicht verlassen können CFFI magisch das Richtige zu tun, aber stattdessen, wie Sie vermutet haben, sollten Sie free() aussetzen. Sie können auch die gc verwenden, wie von Barmar vorgeschlagen, eine automatische Bereinigung zu registrieren, wenn nötig:

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

Danke! Das ist der Teil in der Dokumentation, den ich verpasst habe. Jetzt ist nur noch der zweite Teil übrig - dh, ob ich 'free()' wie oben veröffentlichen muss oder ob CFFI das automatisch tut ('lib.free' existiert nicht, wenn ich es nicht manuell in meinem Browser entpacke) cdef) – ThiefMaster

+0

Wenn Sie wissen, dass das Objekt mit 'malloc()' dynamisch zugewiesen wurde, können Sie 'ffi.gc()' verwenden, um 'lib.free' zu ​​registrieren, um es zurückzufordern. – Barmar

Verwandte Themen