Perl verwendet automatisches Speichermanagement durch Referenzzählung. Wenn Sie verschachtelte Strukturen (zum Beispiel Arrays innerhalb von Hashes) erstellen, erhöht oder verringert jedes Element eines Containers die Anzahl der Verweise auf ein bestimmtes Objekt. Wenn die Anzahl der Verweise null wird, wird der Speicher automatisch freigegeben.
Besondere Aufmerksamkeit sollte zyklischen Verweisen gewidmet werden, die Perl nicht selbstständig freigeben kann – dies ist eine klassische Falle beim Arbeiten mit verschachtelten Strukturen. Perl unterstützt auch schwache Verweise durch das Modul Scalar::Util, was es ermöglicht, Zyklen zu durchbrechen: Ein schwacher Verweis erhöht den Referenzzähler nicht.
my %hash_of_arrays; $hash_of_arrays{"nums"} = [1,2,3]; $hash_of_arrays{"words"} = ["apple", "banana"];
my $a = {}; my $b = { next => $a }; $a->{next} = $b; # Hier entsteht ein Zyklus dump($a); # Verwenden Sie Data::Dumper, um die Struktur anzuzeigen
Um Speicherlecks zu vermeiden, werden schwache Verweise verwendet:
use Scalar::Util qw(weaken); $a->{next} = $b; weaken($a->{next}); # Jetzt ist $a->{next} ein schwacher Verweis
Was passiert mit dem Speicher, wenn man in Perl nur die äußeren Variablen löscht, die zyklisch verbundene Verweise zwischen einem Array und einem Hash enthalten?
Richtige Antwort: Der Referenzzähler eines der Objekte wird nicht auf null gesetzt, da jedes auf das andere verweist; der Speicher wird nicht freigegeben – es entsteht ein Speicherleck! Man muss die Zyklen manuell durchbrechen (zum Beispiel über schwache Verweise).
my $arr = []; my $h = { arr => $arr }; push @$arr, $h; # Jetzt bilden $arr und $h einen Zyklus. Nach undef $arr; undef $h; wird der Speicher nicht freigegeben.
Geschichte
Geschichte
Geschichte
Bei der Implementierung von Caching innerhalb einer CGI-Anwendung wurde beschlossen, komplexe, miteinander verbundene Strukturen (Arrays und Hashes) zu verwenden. Aufgrund der falschen Nullsetzung von alten Werten verwies ein Element des Arrays weiterhin auf den Hash der gesamten Struktur, und der Speicher wurde zwischen HTTP-Anfragen nicht freigegeben, was zu einem Anstieg des Speicherverbrauchs des Apache-Prozesses führte.