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ß
[C] Py_BuildValue und return
-
- User
- Beiträge: 221
- Registriert: Sonntag 1. Juni 2008, 09:08
Hi.
Eine andere Frage auch bezüglich der Memory Leaks.
Übernimmt PyList_Append die Referenz, oder nicht?
Gruß
Eine andere Frage auch bezüglich der Memory Leaks.
Übernimmt PyList_Append die Referenz, oder nicht?
Gruß
Grüßle.
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.
Code: Alles auswählen
def test():
a = c_func()
return
-
- User
- Beiträge: 996
- Registriert: Mittwoch 9. Januar 2008, 13:48
Chrisber, die Routine, die dann das `PyObject` bekommt, muss sich drum kümmern, dass das Objekt `Py_DECREF`d wird. So einfach ist das :-)
-
- User
- Beiträge: 996
- Registriert: Mittwoch 9. Januar 2008, 13:48
Jau, aber nur, wenn der aufrufende Funktion nicht als Extension geschrieben wird -- da muss man das manuell machen.HerrHagen hat geschrieben:Wenn die Funktion jedoch verlassen wird wird es vernichtet.
-
- User
- Beiträge: 996
- Registriert: Mittwoch 9. Januar 2008, 13:48
Um die andere Frage zu beantworten, hier ein Auszug aus "Objects/listobject.c":
und `app1` sieht so aus:
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.
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;
}
Code: Alles auswählen
static int
app1(PyListObject *self, PyObject *v)
{
[snip]
Py_INCREF(v);
PyList_SET_ITEM(self, n, v);
return 0;
}
-
- User
- Beiträge: 221
- Registriert: Sonntag 1. Juni 2008, 09:08
Okay. Danke an alle
Gruß
Gruß
Grüßle.
-
- User
- Beiträge: 221
- Registriert: Sonntag 1. Juni 2008, 09:08
Würde das ganze gerne noch einmal nach oben holen. Danke!
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.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
Grüßle.
-
- User
- Beiträge: 996
- Registriert: Mittwoch 9. Januar 2008, 13:48
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.
-
- User
- Beiträge: 221
- Registriert: Sonntag 1. Juni 2008, 09:08
Hi.
Danke, wusste gar nicht dass es sowas gibt.
Wenn man sich den Makro genauer anschaut, sieht man:
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:
Edit2:
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
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:
Gruß// Don't forget to apply Py_INCREF() when returning this value!!!
Grüßle.