Подтвердить что ты не робот

Сбор мусора в Perl

В отличие от Java, Perl использует счетчик ссылок для сбора мусора. Я попытался найти некоторые предыдущие вопросы, которые говорят о С++ RAII и интеллектуальных указателях и Java GC, но не понял, как Perl имеет дело с круговой ссылкой.

Может ли кто-нибудь объяснить, как сборщик мусора Perl имеет дело с круговыми ссылками? Есть ли способ вернуть круговую память, которая больше не используется программой, или Perl просто полностью игнорирует эту проблему?

4b9b3361

Ответ 1

Согласно моей копии программирования Perl 3rd ed., на выходе Perl 5 делает "дорогой знак и развертку" для возврата круговых ссылок. Вы должны избегать циклических ссылок, насколько это возможно, потому что иначе они не будут восстановлены до выхода программы.

Perl 5 предлагает слабые ссылки через модуль Scalar:: Utils.

Perl 6 переместится на подключаемую схему сбора мусора (ну, базовая виртуальная машина будет иметь несколько опций сбора мусора и поведение этих параметры могут влиять на Perl). То есть, вы сможете выбирать между различными сборщиками мусора или реализовывать свои собственные. Хотите копировального коллекционера? Конечно. Хотите раскрасить? Ты понял. Марк/развертка, уплотнение и т.д.? Почему бы и нет?

Ответ 2

Быстрый ответ: Perl 5 автоматически выполняет не циклические ссылки. Если вы не принимаете явные меры в своем коде, любая из ваших структур данных, которая включает циклические ссылки, не будет исправлена ​​до тех пор, пока нить, которая их создала, не умрет. Это считается приемлемым компромиссом в том, что он позволяет избежать необходимости сбора мусора во время выполнения, что замедлит выполнение.

Если ваш код создает структуры данных с циклическими ссылками (то есть дерево, чьи узлы содержат ссылки обратно к корню), вы захотите использовать модуль Scalar:: Util для "ослабления" ссылок, обращенных к корню node. Эти слабые ссылки не будут добавляться к ссылочному счету того, на что они указывают, поэтому вся структура данных будет автоматически освобождена, когда последняя внешняя ссылка исчезнет.

Пример:

use Scalar::Util qw(weaken);

...

    my $new_node = { content => $content, root => $root_node };
    weaken $new_node->{root};
    push @{$root_node->{children}}, $new_node;

Если вы используете такой код, когда вы добавляете новые узлы в свою структуру данных, то единственными ссылками на корень, которые на самом деле считаются, являются те, что находятся вне структуры. Это именно то, что вы хотите. Тогда корень и рекурсивно все его дети будут восстановлены, как только последняя внешняя ссылка на него исчезнет.

Ответ 4

Perl в некоторых случаях (когда, например, нить умирает, как я полагаю) применяет альтернативный GC с меткой и разверткой, чтобы вернуть круговые ссылки. Обратите внимание, что "каждое значение является строкой". Строка Perl затрудняет создание настоящих круговых ссылок; это возможно, но "нормальный" код Perl этого не делает, поэтому подсчет ссылок хорошо работает с Perl.