什么时候匿名数组/哈希会在perl中被垃圾收集?

时间:2011-06-24 12:24:24

标签: perl garbage-collection

我知道perl无法检测到递归引用:

$a = \$a;
在这种情况下,

$a永远不会被GC。

怎么样:

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

{1,2,3}超出范围时,是否会收集匿名[1,2,3]@a

如何证明是或否?

5 个答案:

答案 0 :(得分:6)

@a = ({1,2,3}, [1,2,3]);超出范围时,其引用计数将减少一个*。

当引用计数@a达到零时,其值的引用计数将减1,并且将被释放。

当引用计数$a[0](对哈希的引用)达到零时,引用哈希的引用计数将减1,并且将被释放。

当匿名哈希的引用计数达到零时,其值的引用计数将减1,并且将被释放。

当其中一个匿名散列值的引用计数达到零时,其值的引用计数将减1,并且将被释放。

同样适用于$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

* - 实际实施因优化而不同。

答案 1 :(得分:2)

如果你使用Scalar::Utilweaken函数“弱化”它们,Perl可以垃圾收集循环引用:

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有几个相关条目:

答案 2 :(得分:0)

如果没有更多内容引用匿名哈希,它将被收集 This会给你一个完整的答案!

答案 3 :(得分:0)

另一种证明内部元素在超出范围时将被GC的方法:

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'
''

  

weaken REF

     

REF将变成弱参考。这意味着它   将不会持有参考计数   它引用的对象。也是当   该对象的引用计数达到   零,REF将设置为undef。

     

这对于保留副本很有用   参考,但你不想   防止对象被DESTROY-ed   通常的时间。

答案 4 :(得分:0)

实际上,当数组/哈希超出范围时,其values(键中的引用只是作为字符串,因此不会影响refcount)会减少refcount ,如果达到0,则操作将递归执行。