ProgrammierungBackend-Entwickler

Erklären Sie, wie das Speichermanagement in Python funktioniert, einschließlich des Garbage Collectors. Was sind zirkuläre Referenzen, und wie geht Python damit um?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

In Python wird der Speicher automatisch verwaltet: Bei der Erstellung eines Objekts wird Speicher zugewiesen, und wenn kein anderes Objekt mehr auf das Objekt verweist, wird der Speicher freigegeben. Die Hauptstrategie ist Referenzzählung: Jedes Objekt hat einen Referenzzähler, wenn dieser null wird — wird das Objekt gelöscht.

Es können jedoch zirkuläre Referenzen entstehen, wenn Objekte sich gegenseitig referenzieren und ihr Referenzzähler nie auf null sinkt, selbst wenn externe Referenzen gelöscht werden.

Um dagegen anzukämpfen, gibt es in Python (CPython) einen Garbage Collector (GC), der Zyklen von Objekten erkennt, die nicht mehr von Wurzeln aus erreichbar sind, und diese entfernt. Der Garbage Collector kann über das Modul gc gesteuert werden.

Beispiel für einen Zyklus:

class Node: def __init__(self): self.ref = None n1 = Node() n2 = Node() n1.ref = n2 n2.ref = n1 del n1, n2 # Objekte sind wegen der zirkulären Referenz immer noch aktiv!

Trickfrage

Frage: „Wenn del obj aufgerufen wird, wird der Speicher immer sofort freigegeben. Stimmt das?“

Antwort: Nein! Die Operation del entfernt lediglich eine Referenz auf ein Objekt. Wenn irgendwo (explizit oder zirkulär) andere Referenzen bestehen, wird der Speicher nicht freigegeben, bis der Referenzzähler null ist und/oder der GC keine Zyklen entfernt hat. Beispiel:

import gc class A: pass x = A() y = x del x # y hat noch eine Referenz, das Objekt ist aktiv! del y # erst jetzt kann das Objekt gelöscht werden

Beispiele für reale Fehler aufgrund mangelnden Wissens über die Nuancen des Themas


Geschichte

In einem System zur Verarbeitung großer Dateien wurden verbundene Objekte im Speicher gehalten. Nach dem Löschen externer Referenzen wurde der Speicher trotzdem nicht freigegeben. Der Grund waren zirkuläre Referenzen, die nicht sofort bereinigt wurden und manchmal überhaupt nicht, aufgrund des Vorhandenseins eines Destruktors __del__.


Geschichte

In einem langlebigen Serverprozess wurden häufig große temporäre Strukturen mit zirkulären Graphen erstellt. Die Entwickler hatten die temporäre Debug-Ausgabe des GC nicht deaktiviert, was zu seltenen, aber spürbaren Pausen führte. Diese wurden als „Leistungsminderungen“ diagnostiziert. Es stellte sich heraus, dass der häufige Start des Garbage Collectors schuld war.


Geschichte

Beim Portieren eines großen Projekts auf PyPy (einen alternativen Interpreter) verließ sich der alte Code auf das spezifische Verhalten von CPython bei der sofortigen Speicherfreigabe über den Referenzzähler — in PyPy wurden Objekte nicht sofort, sondern „auf Wunsch“ des GC gelöscht und bereinigt, was zu unvorhersehbarem Verhalten bei offenen Dateien und Netzwerkverbindungen führte.