Ich programmiere auf Ubuntu, mit Python 2.7.3
.Python CFFI Speicherverwaltungsprobleme
Ich verwende CFFI, um eine Python-Liste mit Werten aus C-Code zu füllen.
Diese Liste ist ziemlich groß: rund 71 000 Zeichen lang, wenn gedruckt.
Der C-Code verwendet viele Bibliotheken. Daher dient der folgende Code nur zum besseren Verständnis dessen, was gerade passiert.
datas_list = []
for i in range(0, x):
c_pDataStructure = ffi.new("c_DataStructure[]", 1) // Create a pointer to the data structure
c.SomeCFunction(c_pDataStructure) // Populate the data structure
datas_list.append(c.GetSomeInfo(c_pDataStructure)) // Get some info from the data structure
c.FreeDataStructure(c_pDataStructure) // Release dynamically allocated memory
Das Programm läuft gut Wingware IDE aber endet mit einem glibc Fehler (*** glibc detected *** python: free(): invalid next size (fast): 0x0000000003b0b080 ***
), wenn von der Kommandozeile, direkt vor gestartet:
c_pDataStructure = ffi.new("c_Datastructure[]", 1)
Nach der Lektüre wims answer, überprüfte ich, wenn sowohl die IDE und die Befehlszeile führten den Code mit dem gleichen Interpreter aus - sie sind (/usr/bin/python
).
EDIT (valgrind Bericht):
==5089== Process terminating with default action of signal 11 (SIGSEGV)
==5089== General Protection Fault
==5089== at 0x54FBB0: PyObject_Malloc (in /usr/bin/python2.7)
==5089== by 0x10B30625: allocate_owning_object (_cffi_backend.c:2972)
==5089== by 0x10B40EE8: allocate_with_allocator.constprop.84 (_cffi_backend.c:3032)
==5089== by 0x10B41010: direct_newp (_cffi_backend.c:3153)
==5089== by 0x10B4138C: b_newp (_cffi_backend.c:3177)
==5089== by 0x4F95A4: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x5008C1: PyEval_EvalCodeEx (in /usr/bin/python2.7)
==5089== by 0x4F9AB7: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
==5089== by 0x4F9D01: PyEval_EvalFrameEx (in /usr/bin/python2.7)
EDIT:
Hier sind einige weitere Informationen über das C-Datenstruktur. Dies ist, wie es aussieht:
typedef struct _STRUCT3{
some int, char*
}STRUCT3, *PSTRUCT3;
typedef struct _STRUCT2{
some int
PSTRUCT3 pStruct3;
}STRUCT3, *PSTRUCT3;
typedef struct _STRUCT1{
some int, char*
PSTRUCT2 pStruct2;
}STRUCT1, *PSTRUCT1;
Ich machte ein kleines C-Programm Zuweisen/Frei eine vollständige C-Struktur und valgrind
kein Speicherleck gefunden.
Fragen:
- Was bedeutet die oben
valgrind
Bericht bedeutet das genau? - Was könnten die Unterschiede zwischen dem Ausführen des Programms von der IDE und von der Befehlszeile sein?
Hinweis: Die IDE verwendet das Python-Argument-u (unbuffered)
, um das Programm auszuführen, aber das Hinzufügen zur Befehlszeile macht keinen Unterschied. - Wenn ich die Struktur selbst auflösche, handelt Pythons Garbage Collector? Sollte ich stattdessen
ffi.gc(c_pDataStructure, c.FreeDataStructure)
verwenden?
'FreeDataStructure (p)' sollte den Zeiger '' p'' selbst nicht freigeben, sondern nur jedes dynamisch zugewiesene Material. Ich denke, das ist der Fall? –
Ja, FreeDataStructure gibt alles frei, was die Populationsfunktion dynamisch zuweist – DRz
Das Programm stürzt ab, nachdem eine Datenstruktur mit einem optionalen Member zum 33. Mal zugewiesen wurde. Daher vermute ich, dass der optionale Wert nicht ordnungsgemäß freigegeben wird. Ist Python (oder CFFI oder C?) Auf einen "32-Speicheradressbereich" geschrumpft, bevor die zuvor verwendete Speicheradresse überschrieben wurde? Dann, wenn Wingware das Programm auf einem 64-Bit-Python und die Befehlszeile auf einem 32-Bit-Python ausführt, könnte es erklären, warum letzteres in einem Glibc-Fehler endet ... Ich untersuche dieses – DRz