Seite 1 von 1
[C] Py_BuildValue und return
Verfasst: Sonntag 23. Mai 2010, 13:53
von theliquidwave
Hallo.
Py_BuildValue erstellt ja eine neue Referenz auf ein Objekt. Entsteht hiermit nicht zwangsweise ein Memory-Leak?
http://www.python-forum.de/pastebin.php?mode=view&s=19
Es gibt für mich ja keine Möglichkeit mehr, den Reference Count zu verändern :K
Gruß
Re: [C] Py_BuildValue und return
Verfasst: Montag 24. Mai 2010, 16:51
von theliquidwave
Hi.
Eine andere Frage auch bezüglich der Memory Leaks.
Übernimmt PyList_Append die Referenz, oder nicht?
Gruß
Re: [C] Py_BuildValue und return
Verfasst: Dienstag 25. Mai 2010, 18:26
von HerrHagen
1.Frage: Ich bin kein Experte auf diesem Gebiet, aber: Du erzeugst ja ein neues Objekt, dieses erhält sogleich eine Referenz welche dann über return aus der Funktion übergeben wird. Das Löschen des Objektes und das Dereferenzieren geschieht ja dann ausserhalb. In diesem Fall:
Wird die Referenz des in der Funktion erzeugten Objektes direkt an a weitergereicht. Wenn die Funktion jedoch verlassen wird wird es vernichtet. Ich seh also kein Speicherleck.
Re: [C] Py_BuildValue und return
Verfasst: Mittwoch 26. Mai 2010, 11:51
von Dauerbaustelle
Chrisber, die Routine, die dann das `PyObject` bekommt, muss sich drum kümmern, dass das Objekt `Py_DECREF`d wird. So einfach ist das :-)
Re: [C] Py_BuildValue und return
Verfasst: Mittwoch 26. Mai 2010, 11:52
von Dauerbaustelle
HerrHagen hat geschrieben:Wenn die Funktion jedoch verlassen wird wird es vernichtet.
Jau, aber nur, wenn der aufrufende Funktion nicht als Extension geschrieben wird -- da muss man das manuell machen.
Re: [C] Py_BuildValue und return
Verfasst: Mittwoch 26. Mai 2010, 11:55
von Dauerbaustelle
Um die andere Frage zu beantworten, hier ein Auszug aus "Objects/listobject.c":
Code: Alles auswählen
int
PyList_Append(PyObject *op, PyObject *newitem)
{
if (PyList_Check(op) && (newitem != NULL))
return app1((PyListObject *)op, newitem);
PyErr_BadInternalCall();
return -1;
}
und `app1` sieht so aus:
Code: Alles auswählen
static int
app1(PyListObject *self, PyObject *v)
{
[snip]
Py_INCREF(v);
PyList_SET_ITEM(self, n, v);
return 0;
}
Antwort: Es erhöht den Referenzzähler des übergebenen Objektes. Genau so verhält es sich dann, wenn die Liste entfernt wird bzw. das Objekt aus der Liste: Der Referenzzähler wird vermindert.
Re: [C] Py_BuildValue und return
Verfasst: Mittwoch 26. Mai 2010, 18:17
von theliquidwave
Okay. Danke an alle
Gruß
Re: [C] Py_BuildValue und return
Verfasst: Sonntag 6. Juni 2010, 00:03
von theliquidwave
Würde das ganze gerne noch einmal nach oben holen. Danke!
Chrisber hat geschrieben:Py_BuildValue erstellt ja eine neue Referenz auf ein Objekt. Entsteht hiermit nicht zwangsweise ein Memory-Leak?
http://www.python-forum.de/pastebin.php?mode=view&s=19
Es gibt für mich ja keine Möglichkeit mehr, den Reference Count zu verändern :K
Edit: Wenn ich Py_True / Py_False returne (was ja offensichtlich funktioniert) - wie sieht es da mit dem Reference Count aus? Kann dazu nichts finden.
Re: [C] Py_BuildValue und return
Verfasst: Sonntag 6. Juni 2010, 00:36
von Dauerbaustelle
Eigentlich müsstest du den Referenzcounter für `True` und `False` und `None` wie jeden anderen Referenzcounter behandeln -- aber es wird wohl niemals geschehen, dass `True` oder `False` oder `None` dealloziert werden. Es gibt aber zum Beispiel für das Zurückgeben von `None` extra das Makro `Py_RETURN_NONE`, also sollte es auch nicht besonders schwer sein, den Referenzcounter richtig zu managen.
Re: [C] Py_BuildValue und return
Verfasst: Sonntag 6. Juni 2010, 01:14
von theliquidwave
Hi.
Danke, wusste gar nicht dass es sowas gibt.
Wenn man sich den Makro genauer anschaut, sieht man:
Code: Alles auswählen
/* Macro for returning Py_None from a function */
#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
Wenn man das schlussfolgert sollte sich auch meine Frage beantworten: Python macht den Reference Count automatisch um einen niedriger nach einem "return", oder? Sonst hätte die API an dieser Stelle ja selbst einen Leck.
Edit:
Code: Alles auswählen
/* Macros for returning Py_True or Py_False, respectively */
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
Edit2:
// Don't forget to apply Py_INCREF() when returning this value!!!
Gruß