开发者

When will anonymous array/hash be garbage collected in perl?

I know that perl can't detect the recursive reference as :

$a = \$a;

$a will never be GCed in this开发者_Go百科 case.

What about :

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

Will the anonymous {1,2,3} and [1,2,3] be collected when @a goes out of scope?

How to prove it's yes or no?


When @a = ({1,2,3}, [1,2,3]); goes out of scope, its reference count will be reduced by one*.

When the reference count of @a reaches zero, the reference count of its values will be reduced by one, and it will be freed.

When the reference count of $a[0] (a reference to a hash) reaches zero, the reference count of the referenced hash will be reduced by one, and it will be freed.

When the reference count of the anonymous hash reaches zero, the reference count of the its values will be reduced by one, and it will be freed.

When the reference count of one of the anonymous's hash's values reaches zero, the reference count of the its values will be reduced by one, and it will be freed.

Same goes for $a[1], the array it references and the values of that array.

You can "prove" this by using objects with destructors.

$ 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

* — Actual implementation differs as an optimisation.


Perl can garbage-collect circular references if you "weaken" them using 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.

As far as garbage-collecting things that have gone out of scope, there's no one answer. It depends on your operating system and how perl was compiled. It's not something you should generally be worried about. perlfaq3 has a couple of relevant entries:

  • How can I make my Perl program take less memory?
  • How can I free an array or hash so my program shrinks?


If there is nothing more referring the anonymous hash it will be collected.
This will give you a complete answer!


Another way to prove that the inner elements will be GCed when out of scope:

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

Outputs:

'bar'
''

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.

This is useful for keeping copies of references , but you don't want to prevent the object being DESTROY-ed at its usual time.


Actually when an array/hash goes out of scope,its values(the reference in keys are just taken as string so won't impact the refcount) will decrease their refcount,and if reaches 0,the operation will performe recursively.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜