Perl использует автоматическое управление памятью через счётчики ссылок (reference counting). Когда вы строите вложенные структуры (например, массивы внутри хэшей), каждый элемент любого контейнера увеличивает либо уменьшает число ссылок на тот или иной объект. Когда число ссылок становится нулевым, память освобождается автоматически.
Особое внимание следует уделять циклическим ссылкам, которые Perl не умеет освобождать самостоятельно — это классическая ловушка в работе с вложенными структурами. Perl также поддерживает слабые ссылки через модуль Scalar::Util, что позволяет разорвать циклы: слабая ссылка не увеличивает счётчик ссылок.
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; # Здесь возникает цикл dump($a); # Используйте Data::Dumper для просмотра структуры
Чтобы избежать утечек, применяют слабые ссылки:
use Scalar::Util qw(weaken); $a->{next} = $b; weaken($a->{next}); # Теперь $a->{next} — слабая ссылка
Что произойдет с памятью, если в Perl удалить только внешние переменные, содержащие циклически связанные ссылки между массивом и хэшем?
Правильный ответ: Счётчик ссылок ни в одном из объектов не обнулится, т.к. каждый будет ссылаться на другой; память не освободится — возникнет утечка! Нужно вручную разрывать циклы (например, через слабые ссылки).
my $arr = []; my $h = { arr => $arr }; push @$arr, $h; # Теперь $arr и $h образуют цикл. После undef $arr; undef $h; память не освобождается.
История
История
История
При реализации кэширования внутри CGI-приложения решили использовать сложные взаимосвязанные структуры (массивы и хэши). Из-за неправильного обнуления старых значений один из элементов массива продолжал ссылаться на хэш всей структуры, и память не освобождалась между HTTP-запросами, что вызывало рост памяти процесса Apache.