Perl używa automatycznego zarządzania pamięcią za pomocą liczników referencji. Kiedy tworzysz zagnieżdżone struktury (na przykład tablice wewnątrz hashy), każdy element dowolnego kontenera zwiększa lub zmniejsza liczbę referencji do danego obiektu. Kiedy liczba referencji staje się zerowa, pamięć jest automatycznie zwalniana.
Należy zwrócić szczególną uwagę na cykliczne odwołania, które Perl nie jest w stanie zwolnić samodzielnie — to klasyczna pułapka w pracy z zagnieżdżonymi strukturami. Perl wspiera również słabe referencje przez moduł Scalar::Util, co pozwala przerwać cykle: słaba referencja nie zwiększa licznika referencji.
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; # Tutaj występuje cykl dump($a); # Użyj Data::Dumper do wyświetlenia struktury
Aby uniknąć wycieków, używa się słabych referencji:
use Scalar::Util qw(weaken); $a->{next} = $b; weaken($a->{next}); # Teraz $a->{next} jest słabą referencją
Co się stanie z pamięcią, jeśli w Perl usuniemy tylko zewnętrzne zmienne zawierające cyklicznie powiązane referencje między tablicą a hashem?
Poprawna odpowiedź: Licznik referencji w żadnym z obiektów nie zostanie zera, ponieważ każdy będzie wskazywał na inny; pamięć nie zostanie zwolniona — wystąpi wyciek! Należy ręcznie przerwać cykle (na przykład za pomocą słabych referencji).
my $arr = []; my $h = { arr => $arr }; push @$arr, $h; # Teraz $arr i $h tworzą cykl. Po undef $arr; undef $h; pamięć nie jest zwalniana.
Historia
Historia
Historia
Podczas implementacji cachowania w aplikacji CGI zdecydowano się używać złożonych powiązanych struktur (tablice i hashe). Z powodu niewłaściwego zerowania starych wartości jeden z elementów tablicy nadal odnosił się do hasha całej struktury i pamięć nie była zwalniana między żądaniami HTTP, co powodowało wzrost pamięci procesu Apache.