Когда анонимный массив / хэш будет собирать мусор в Perl? - PullRequest
2 голосов
/ 24 июня 2011

Я знаю, что Perl не может обнаружить рекурсивную ссылку как:

$a = \$a;

$a никогда не будет GCed в этом случае.

А как же:

@a = ({1,2,3}, [1,2,3]);

Будут ли анонимные {1,2,3} и [1,2,3] собраны, когда @a выйдет из области видимости?

Как доказать, что это да или нет?

Ответы [ 5 ]

6 голосов
/ 24 июня 2011

Когда @a = ({1,2,3}, [1,2,3]); выходит из области видимости, его счетчик ссылок будет уменьшен на один *.

Когда счетчик ссылок @a достигнет нуля, счетчик ссылок его значений будет уменьшен на единицу, и он будет освобожден.

Когда счетчик ссылок $a[0] (ссылка на хеш) достигает нуля, счетчик ссылок ссылочного хеша уменьшается на единицу и освобождается.

Когда счетчик ссылок анонимного хэша достигнет нуля, счетчик ссылок его значений будет уменьшен на единицу, и он будет освобожден.

Когда счетчик ссылок одного из хеш-значений анонима достигает нуля, счетчик ссылок его значений уменьшается на единицу и освобождается.

То же самое относится к $a[1], массиву, на который он ссылается, и значениям этого массива.

Вы можете «доказать» это, используя объекты с деструкторами.

$ perl -E'
   package X {
      sub new { my ($c,$n) = @_; bless(\$n, $c) }
      DESTROY { say ${$_[0]}; }
   }
   {
      my @a = (
         { a => X->new(1), b => X->new(2) },
         [ X->new(3), X->new(4) ],
      );
      say "Before end of scope";
   }
   say "After end of scope";
'
Before end of scope
4
3
2
1
After end of scope

* & mdash; Фактическая реализация отличается как оптимизация.

2 голосов
/ 24 июня 2011

Perl может собирать мусорные циклические ссылки, если вы "ослабили" их, используя Scalar :: Util 's weaken function:

weaken REF
    REF will be turned into a weak reference. This means that it will
    not hold a reference count on the object it references. Also when
    the reference count on that object reaches zero, REF will be set to
    undef.

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

0 голосов
/ 26 июня 2011

На самом деле, когда массив / хеш выходит из области видимости, его values (ссылка в ключах просто берется как строка, поэтому не влияет на refcount) уменьшит их refcount, а если достигнет 0 операция будет выполняться рекурсивно.

0 голосов
/ 24 июня 2011

Еще один способ доказать, что внутренние элементы будут GCed, когда они выходят за рамки:

use Scalar::Util 'weaken';

my $x;

{
    my @a = ({foo => 'bar'}, ['foo', 'bar']);

    $x = $a[1]; # ref to the inner array
    weaken $x; # weaken the ref, so it doesn't interfere with GC
    print "'$x->[1]'\n"; # show us what we got
}

print "'$x->[1]'\n"; # and now it's gone

Выходы:

'bar'
''

ослабить REF

REF будет превращен в слабую ссылку. Это означает, что это не будет держать счетчик ссылок на возражать это ссылки. Также когда счетчик ссылок на этот объект достигает ноль, REF будет установлен на undef.

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

0 голосов
/ 24 июня 2011

Если больше нет ссылок на анонимный хеш, он будет собран.
Этот даст вам полный ответ!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...