@hypnoticum: Das ist schon wieder alles so ohne wirkliche Fehlerbehandlung. Das ist kein robuster Code, da können noch ganz andere schlimme Dinge passieren. Zum Beispiel stellst Du in keiner Weise sicher, dass die Listen am Ende auch an jedem Index ein gültiges Python-Objekt stehen haben.
Deine letzte Frage im ersten Beitrag stellt sich so gar nicht weil Du nirgends `PyObject`\s etwas zuweist, sondern immer nur mit Zeigern auf solche Strukturen arbeitest. Du überschreibst also nie ein `PyObject`. Wenn Du allerdings wiederholt einem Zeiger `PyObject`\s zuweist und dabei einen vorherigen Zeiger auf so ein Objekt überschreibst auf das Du nicht anderweitig noch heran kommst, und für das Du die Verantwortung hast den Zähler zu verringern wenn Du es nicht mehr benötigst, dann hast Du an der Stelle ein Speicherleck. *Ob* Du diese Verantwortung hast, hängt davon ab auf welchem Weg Du an den Zeiger gekommen bist. Da musst Du aufmerksam die Dokumentation lesen, wie EyDu ja schon gesagt hat.
Deine Namen sind IMHO übrigens sehr verwirrend.
Der Programmablauf erscheint auch wenig durchdacht. Vor der Schleife wird zum Beispiel `PyCallModule` etwas zugewiesen, was dann erst *in* der Schleife bei jedem Durchlauf getestet wird, ob das überhaupt erfolgreich war. Falls es das nicht wahr wird an Python komplett vorbei eine Fehlermeldung ausgegeben und es wird danach dann trotzdem geprüft ob `PyCallMethod` — was in diesem Fall gar nicht an einen gültigen Wert gebunden sein *kann* — etwas aufrufbares ist. Falls das nicht schon abstürzt geht dieses Spielchen fröhlich alle Schleifendurchläufe weiter, wobei immer neue Dateien geöffnet werden (`ResultFile`), die nicht wieder geschlossen werden. Das ist Murks.
Ein Speicherleck hast Du da wohl bei `PyRetVal`. Und beim innersten ``if`` beim `PyString_FromString()`-Rückgabewert wohl auch.
Warum Du `PyCallMethod` nicht `PY_DECREF`\fen darfst steht in der Dokumentation zu `PyDict_GetItemString()`. So ziemlich bei jeder Funktion die einen Zeiger auf ein `PyObject` liefert, steht wem die Referenz gehört.
Auch das hier ist wieder ein Quelltext bei dem ich nicht verstehe warum der in C geschrieben sein muss. Gerade weil Du offensichtlich nicht so gut programmieren kannst, hättest Du bei Python den Vorteil das Du keine Speicherverwaltung betreiben musst, und dass das Programm bei Fehlern viel sicherer, wohldefiniert, und sauberer reagiert. Und das auch noch mit einem ordentlichen Stacktrace der bei der Fehlersuche hilft, statt einfach so hart abzustürzen.
Es ist kein raten wenn man bei einem Absturz den Quelltext systematisch nach Fehlern durchsucht. Ich habe den ziemlich zielsicher gefunden, in dem ich mir angeschaut habe wo dem Zeiger etwas zugewiesen wird und was die Dokumentation zu der Funktion an der Stelle zu sagen hat. Das hat nichts mit raten zu tun.
Edit: Um das mit der Sprache noch einmal zu illustrieren habe ich auch den Quelltext mal in Python formuliert:
Code: Alles auswählen
from device.name import ext
# ...
a_dict = {
'times': str(times),
'AvgCN0Key': AVGCN0_KEY,
}
abscissas = list()
ordinates = list()
for _ in xrange(frequency_steps + 1):
result_file.write('\n%s\t%f\n' % (FREQ_KEY, frequency))
abscissas.append(frequency)
ordinates.append(ext.GPS_CN0Avg(device, a_dict, filepath)[VAL_KEY])
Keine Speicherlecks und keine Abstürze die schwer zu finden sind, dafür aber wesentlich weniger Quelltext.
Beim „Übersetzen“ habe ich übrigens noch ein Speicherleck entdeckt: `PyCallDict`.