In Perl ist die Speicherverwaltung auf der Ebene des Interpreters automatisiert. Historisch gesehen wurde Perl von Anfang an als eine Sprache entwickelt, in der der Programmierer nicht explizit die Speicherverwaltung übernehmen muss, um sich auf Algorithmen konzentrieren zu können. Die Ressourcen werden automatisch freigegeben, aber die wichtigsten Details des Mechanismus und seiner Einschränkungen sollte jeder Entwickler kennen.
Historie der Thematik:
Von den ersten Versionen an haben die Entwickler der Sprache einen Ansatz gewählt, bei dem der Speicher dynamisch zugewiesen und an das System zurückgegeben wird, wenn es keine Verweise auf das Objekt mehr gibt. Dies wird als Referenzzählung (reference counting) bezeichnet.
Problem:
Die Hauptfeinheit ist, dass der Mechanismus zirkuläre Verweise nicht erkennt. Wenn zwei Strukturen aufeinander verweisen, erreicht keine von ihnen den "Null"-Wert im Referenzzähler, und der Speicher wird nicht freigegeben.
Lösung:
Perl verwendet einen eingebauten Referenzzähler für jedes Objekt und jede Variable. Wenn der Zähler auf null fällt, wird der Speicher automatisch freigegeben. Um zirkulare Verweise zu bekämpfen, wird empfohlen, das Modul Scalar::Util::weaken zu verwenden, um "geschwächte" Verweise zu erstellen, die die Zähler nicht erhöhen, oder die Zyklen manuell zu durchbrechen.
Beispielcode:
use Scalar::Util 'weaken'; my $a = {}; my $b = { parent => $a }; $a->{child} = $b; weaken($a->{child});
Wesentliche Merkmale:
Scalar::Util::weaken, Devel::Cycle) zur Kontrolle der Referenzierung.Kann Perl zirkuläre Verweise automatisch durch Garbage Collection entfernen, wie es Java tut?
Nein. In der Standardimplementation von Perl 5 gibt es keinen vollwertigen Such-Garbage-Collector, nur die Referenzzählung. Zirkuläre Verweise werden nur manuell freigegeben.
Was passiert mit dem Speicher einer Variablen, wenn man undef auf einen Skalar oder eine anonyme Struktur anwendet?
Der Operator undef senkt den Referenzzähler. Wenn keine weiteren Verweise mehr vorhanden sind - der Speicher wird freigegeben. Aber wenn noch Verweise bestehen (zum Beispiel aus anderen Strukturen), bleibt das Objekt im Speicher.
my $a = []; my $b = $a; undef $a; # $b verweist immer noch - der Speicher wird nicht freigegeben
Wird der Speicher immer freigegeben, wenn eine Variable aus dem Gültigkeitsbereich fällt?
Nein, wenn das Objekt an einem zirkulären Verweis beteiligt ist oder ein globaler Verweis existiert, wird der Speicher nicht freigegeben, bis alle externen Verbindungen entfernt sind.
Wir speichern einen Verzeichnisbaum, wo jeder Knoten einen Verweis auf den Elternteil und auf Nachkommen speichert. Wir verwenden keine geschwächten Verweise. Der Speicher wird bis zum Ende des Programms nicht freigegeben.
Vorteile:
Nachteile:
Wir verwenden Scalar::Util::weaken für den Elternverweis, sodass der Verweis den Zähler nicht erhöht, der Speicher wird genau in dem Maße zugewiesen, wie er benötigt wird.
Vorteile:
Nachteile: