Die Speicherverwaltung in Python umfasst einen privaten Heap, der alle Python-Objekte und Datenstrukturen enthält. Die Verwaltung dieses privaten Heaps wird intern durch den Python-Speichermanager sichergestellt. Der Python-Speichermanager verfügt über verschiedene Komponenten, die sich mit verschiedenen Aspekten der dynamischen Speicherverwaltung befassen, z. B. Freigabe, Segmentierung, Vorbelegung oder Zwischenspeicherung.
Auf der untersten Ebene stellt ein Rohspeicher-Allokator sicher, dass im privaten Heap genügend Platz zum Speichern aller Python-bezogenen Daten vorhanden ist, indem er mit dem Speichermanager des Betriebssystems interagiert. Zusätzlich zum Rohspeicher-Allokator arbeiten mehrere objektspezifische Allokatoren auf demselben Heap und implementieren unterschiedliche Speicherverwaltungsrichtlinien, die an die Besonderheiten jedes Objekttyps angepasst sind. Beispielsweise werden Ganzzahlobjekte innerhalb des Heaps anders verwaltet als Zeichenfolgen, Tupel oder Wörterbücher, da Ganzzahlen unterschiedliche Speicheranforderungen und Kompromisse zwischen Geschwindigkeit und Speicherplatz implizieren. Der Python-Speichermanager delegiert daher einen Teil der Arbeit an die objektspezifischen Allokatoren, stellt jedoch sicher, dass diese innerhalb der Grenzen des privaten Heaps arbeiten.
Es ist wichtig zu verstehen, dass die Verwaltung des Python-Heaps vom Interpreter selbst durchgeführt wird und dass der Benutzer keine Kontrolle darüber hat, selbst wenn er regelmäßig Objektzeiger auf Speicherblöcke innerhalb dieses Heaps bearbeitet. Die Zuweisung von Heap-Speicherplatz für Python-Objekte und andere interne Puffer erfolgt auf Anforderung durch den Python-Speichermanager über die in diesem Dokument aufgeführten Python /C-API-Funktionen.
Um Speicherbeschädigungen zu vermeiden, sollten Erweiterungsschreiber niemals versuchen, damit zu arbeiten Python-Objekte mit den von der C-Bibliothek exportierten Funktionen: malloc() , calloc() , realloc() und free() . Dies führt zu gemischt Aufrufe zwischen dem C-Allokator und dem Python-Speichermanager mit fatal Konsequenzen, weil sie unterschiedliche Algorithmen implementieren und arbeiten verschiedene Haufen. Man kann jedoch sicher Speicherblöcke zuweisen und freigeben mit dem C-Bibliothekszuweiser für einzelne Zwecke, wie im Folgenden gezeigt Beispiel:
PyObject *res; char *buf=(char *) malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); ...Do some I/O operation involving buf... res=PyBytes_FromString(buf); free(buf); /* malloc'ed */ return res;
In diesem Beispiel wird die Speicheranforderung für den E /A-Puffer vom C-Bibliothekszuweiser verarbeitet. Der Python-Speichermanager ist nur an der Zuweisung des als Ergebnis zurückgegebenen Byte-Objekts beteiligt.
In den meisten Situationen wird jedoch empfohlen, Speicher aus dem Python-Heap zuzuweisen, da dieser vom Python-Speichermanager gesteuert wird. Dies ist beispielsweise erforderlich, wenn der Interpreter um neue in C geschriebene Objekttypen erweitert wird. Ein weiterer Grund für die Verwendung des Python-Heaps ist der Wunsch, den Python-Speichermanager über den Speicherbedarf des Erweiterungsmoduls zu informieren. Selbst wenn der angeforderte Speicher ausschließlich für interne, hochspezifische Zwecke verwendet wird, führt das Delegieren aller Speicheranforderungen an den Python-Speichermanager dazu, dass der Interpreter ein genaueres Bild seines gesamten Speicherbedarfs erhält. Infolgedessen kann der Python-Speichermanager unter bestimmten Umständen geeignete Aktionen auslösen, z. B. Speicherbereinigung, Speicherkomprimierung oder andere vorbeugende Verfahren. Beachten Sie, dass bei Verwendung des C-Bibliothekszuweisers wie im vorherigen Beispiel gezeigt der zugewiesene Speicher für den E /A-Puffer vollständig dem Python-Speichermanager entgeht.
{tip} Mit der Umgebungsvariablen PYTHONMALLOC können die von Python verwendeten Speicherzuordnungen konfiguriert werden. Die Umgebungsvariable PYTHONMALLOCSTATS kann verwendet werden, um jedes Mal, wenn ein neues Pymalloc-Objekt erstellt wird, Statistiken des Pymalloc-Speicherzuordners zu drucken Arena wird erstellt und beim Herunterfahren.
Die folgenden Funktionssätze sind Wrapper für den Systemzuordner. Diese Funktionen sind threadsicher, die GIL muss nicht gehalten werden.
Der Standard-Rohspeicherzuweiser verwendet die folgenden Funktionen: malloc() , calloc() , realloc() und free() ; Rufen Sie malloc(1) (oder calloc(1, 1) ) auf, wenn Sie null Bytes anfordern.
Neu in Version 3.4.
Ordnet n Bytes zu und gibt einen Zeiger vom Typ void* an den zugewiesenen Speicher zurück oder NULL , wenn die Anforderung fehlschlägt. Das Anfordern von Null-Bytes gibt nach Möglichkeit einen eindeutigen Nicht- NULL -Zeiger zurück, als ob stattdessen PyMem_RawMalloc(1) aufgerufen worden wäre. Der Speicher wurde in keiner Weise initialisiert.
Ordnet nelem Elemente zu, deren Größe in Bytes elsize ist, und gibt einen Zeiger vom Typ void* an den zugewiesenen Speicher zurück, oder NULL , wenn die Anforderung fehlschlägt. Der Speicher wird auf Nullen initialisiert. Das Anfordern von Nullelementen oder Elementen mit einer Größe von Nullbytes gibt nach Möglichkeit einen eindeutigen Nicht- NULL -Zeiger zurück, als ob stattdessen PyMem_RawCalloc(1, 1) aufgerufen worden wäre. Neu in Version 3.5.
Ändert die Größe des Speicherblocks, auf den p zeigt, auf n Bytes. Der Inhalt bleibt unverändert auf das Minimum der alten und der neuen Größe. Wenn p NULL ist, entspricht der Aufruf PyMem_RawMalloc(n) ; andernfalls, wenn n gleich Null ist, wird die Größe des Speicherblocks geändert, aber nicht freigegeben, und der zurückgegebene Zeiger ist nicht NULL . Sofern p nicht NULL ist, muss es durch einen vorherigen Aufruf an PyMem_RawMalloc() , PyMem_RawRealloc() oder [zurückgegeben worden sein b42] . Wenn die Anforderung fehlschlägt, gibt PyMem_RawRealloc() NULL zurück und p bleibt ein gültiger Zeiger auf den vorherigen Speicherbereich.
Gibt den Speicherblock frei, auf den p zeigt, der durch einen vorherigen Aufruf von PyMem_RawMalloc() , PyMem_RawRealloc() oder [b23 zurückgegeben worden sein muss] PyMem_RawCalloc() . Andernfalls oder wenn PyMem_RawFree(p) zuvor aufgerufen wurde, tritt undefiniertes Verhalten auf. Wenn p NULL ist, wird keine Operation ausgeführt.
Die folgenden Funktionssätze, die dem ANSI C-Standard nachempfunden sind, jedoch das Verhalten beim Anfordern von Null Bytes angeben, stehen zum Zuweisen und Freigeben von Speicher aus dem Python-Heap zur Verfügung.
Der Standardspeicherzuweiser verwendet den Pymalloc-Speicherzuweiser .
{warning} Bei Verwendung dieser Funktionen muss die GIL gehalten werden.
In Version 3.6 geändert: Der Standardzuweiser ist jetzt Pymalloc anstelle von System malloc() .
Ordnet n Bytes zu und gibt einen Zeiger vom Typ void* an den zugewiesenen Speicher zurück oder NULL , wenn die Anforderung fehlschlägt. Das Anfordern von Null-Bytes gibt nach Möglichkeit einen eindeutigen Nicht- NULL -Zeiger zurück, als ob stattdessen PyMem_Malloc(1) aufgerufen worden wäre. Der Speicher wurde in keiner Weise initialisiert.
Ordnet nelem Elemente zu, deren Größe in Bytes elsize ist, und gibt einen Zeiger vom Typ void* an den zugewiesenen Speicher zurück, oder NULL , wenn die Anforderung fehlschlägt. Der Speicher wird auf Nullen initialisiert. Das Anfordern von Nullelementen oder Elementen mit einer Größe von Nullbytes gibt nach Möglichkeit einen eindeutigen Nicht- NULL -Zeiger zurück, als ob stattdessen PyMem_Calloc(1, 1) aufgerufen worden wäre. Neu in Version 3.5.
Ändert die Größe des Speicherblocks, auf den p zeigt, auf n Bytes. Der Inhalt bleibt unverändert auf das Minimum der alten und der neuen Größe. Wenn p NULL ist, entspricht der Aufruf PyMem_Malloc(n) ; andernfalls, wenn n gleich Null ist, wird die Größe des Speicherblocks geändert, aber nicht freigegeben, und der zurückgegebene Zeiger ist nicht NULL . Sofern p nicht NULL ist, muss es durch einen vorherigen Aufruf an PyMem_Malloc() , PyMem_Realloc() oder [zurückgegeben worden sein b42] . Wenn die Anforderung fehlschlägt, gibt PyMem_Realloc() NULL zurück und p bleibt ein gültiger Zeiger auf den vorherigen Speicherbereich.
Gibt den Speicherblock frei, auf den p zeigt, der durch einen vorherigen Aufruf von PyMem_Malloc() , PyMem_Realloc() oder [b23 zurückgegeben worden sein muss] PyMem_Calloc() . Andernfalls oder wenn PyMem_Free(p) zuvor aufgerufen wurde, tritt undefiniertes Verhalten auf. Wenn p NULL ist, wird keine Operation ausgeführt.
Die folgenden typorientierten Makros werden zur Vereinfachung bereitgestellt. Beachten Sie, dass TYP sich auf einen beliebigen C-Typ bezieht.
Wie PyMem_Malloc() , weist jedoch (n * sizeof(TYPE)) Speicherbytes zu. Gibt einen Zeiger zurück, der auf TYPE* umgewandelt wurde. Der Speicher wurde in keiner Weise initialisiert.
Wie PyMem_Realloc() , jedoch wird die Größe des Speicherblocks auf (n * sizeof(TYPE)) Byte geändert. Gibt einen Zeiger zurück, der auf TYPE* umgewandelt wurde. Bei der Rückkehr ist p ein Zeiger auf den neuen Speicherbereich oder NULL im Fehlerfall. Dies ist ein C-Präprozessor-Makro. p wird immer neu zugewiesen. Speichern Sie den ursprünglichen Wert von p , um Speicherverlust bei der Behandlung von Fehlern zu vermeiden.
Darüber hinaus werden die folgenden Makrosätze bereitgestellt, um den Python-Speicherzuweiser direkt aufzurufen, ohne die oben aufgeführten C-API-Funktionen einzubeziehen. Beachten Sie jedoch, dass ihre Verwendung die Binärkompatibilität zwischen Python-Versionen nicht beibehält und daher in Erweiterungsmodulen veraltet ist.
PyMem_MALLOC(size)
PyMem_NEW(type, size)
PyMem_REALLOC(ptr, size)
PyMem_RESIZE(ptr, type, size)
PyMem_FREE(ptr)
PyMem_DEL(ptr)
Die folgenden Funktionssätze, die dem ANSI C-Standard nachempfunden sind, jedoch das Verhalten beim Anfordern von Null Bytes angeben, stehen zum Zuweisen und Freigeben von Speicher aus dem Python-Heap zur Verfügung.
Der Standardobjekt-Allokator verwendet den Pymalloc-Speicher-Allokator .
{warning} Bei Verwendung dieser Funktionen muss die GIL gehalten werden.
Ordnet n Bytes zu und gibt einen Zeiger vom Typ void* an den zugewiesenen Speicher zurück oder NULL , wenn die Anforderung fehlschlägt. Das Anfordern von Null-Bytes gibt nach Möglichkeit einen eindeutigen Nicht- NULL -Zeiger zurück, als ob stattdessen PyObject_Malloc(1) aufgerufen worden wäre. Der Speicher wurde in keiner Weise initialisiert.
Ordnet nelem Elemente zu, deren Größe in Bytes elsize ist, und gibt einen Zeiger vom Typ void* an den zugewiesenen Speicher zurück, oder NULL , wenn die Anforderung fehlschlägt. Der Speicher wird auf Nullen initialisiert. Das Anfordern von Nullelementen oder Elementen mit einer Größe von Nullbytes gibt nach Möglichkeit einen eindeutigen Nicht- NULL -Zeiger zurück, als ob stattdessen PyObject_Calloc(1, 1) aufgerufen worden wäre. Neu in Version 3.5.
Ändert die Größe des Speicherblocks, auf den p zeigt, auf n Bytes. Der Inhalt bleibt unverändert auf das Minimum der alten und der neuen Größe. Wenn p NULL ist, entspricht der Aufruf PyObject_Malloc(n) ; andernfalls, wenn n gleich Null ist, wird die Größe des Speicherblocks geändert, aber nicht freigegeben, und der zurückgegebene Zeiger ist nicht NULL . Sofern p nicht NULL ist, muss es durch einen vorherigen Aufruf an PyObject_Malloc() , PyObject_Realloc() oder [zurückgegeben worden sein b42] . Wenn die Anforderung fehlschlägt, gibt PyObject_Realloc() NULL zurück und p bleibt ein gültiger Zeiger auf den vorherigen Speicherbereich.
Gibt den Speicherblock frei, auf den p zeigt, der durch einen vorherigen Aufruf von PyObject_Malloc() , PyObject_Realloc() oder [b23 zurückgegeben worden sein muss] PyObject_Calloc() . Andernfalls oder wenn PyObject_Free(p) zuvor aufgerufen wurde, tritt undefiniertes Verhalten auf. Wenn p NULL ist, wird keine Operation ausgeführt.
Standardspeicherzuordnungen:
Konfiguration Name PyMem_RawMalloc PyMem_Malloc PyObject_Malloc Build freigeben "pymalloc" malloc pymalloc pymalloc Debug-Build "pymalloc_debug" malloc + Debug pymalloc + Debug pymalloc + Debug Release Build ohne Pymalloc "malloc" malloc malloc malloc Debug-Build ohne Pymalloc "malloc_debug" malloc + Debug malloc + Debug malloc + Debug
Legende: