Perl中的垃圾收集

sri*_*eak 14 perl garbage-collection circular-reference

与Java不同,Perl使用引用计数进行垃圾收集.我曾尝试搜索一些以前的问题,这些问题涉及C++ RAII和智能指针以及Java GC,但还没有理解Perl如何处理循环引用问题.

任何人都可以解释Perl的垃圾收集器如何处理循环引用?有没有办法回收程序不再使用的循环引用内存,或者Perl是否完全忽略了这个问题?

Max*_*ert 13

根据我的Programming Perl 3rd ed的副本.在退出时,Perl 5会进行"昂贵的标记和扫描"来回收循环引用.您将希望尽可能避免循环引用,否则在程序退出之前不会回收它们.

Perl 5通过Scalar :: Utils模块提供弱引用.

Perl 6将转移到可插入垃圾收集方案(好吧,底层VM将有多个垃圾收集选项,这些选项的行为可能对Perl产生影响).也就是说,您可以在各种垃圾收集器之间进行选择,也可以实现自己的垃圾收集器.想要一个复制收藏家?当然.想要一个着色收藏家?你说对了.标记/扫描,压缩等?为什么不?

  • Nit:Perl 5使用引用计数.这是一个垃圾收集计划. (4认同)

小智 5

简单的回答是Perl 5也不会自动处理循环引用。除非您在代码中采取明确的措施,否则在创建它们的线程死亡之前,任何包含循环引用的数据结构都不会被回收。这被认为是一种可接受的折衷,因为它避免了运行时垃圾收集的需要,这会减慢执行速度。

如果您的代码使用循环引用创建数据结构(即,其节点包含指向根节点的引用的树),您将需要使用 Scalar::Util 模块来“弱化”指向根节点的引用。这些弱引用不会增加它们指向的任何引用计数,因此当最后一个外部引用消失时,整个数据结构将自动释放。

例子:

use Scalar::Util qw(weaken);

...

    my $new_node = { content => $content, root => $root_node };
    weaken $new_node->{root};
    push @{$root_node->{children}}, $new_node;
Run Code Online (Sandbox Code Playgroud)

如果每当向数据结构添加新节点时都使用这样的代码,那么实际计算的对根的唯一引用是来自结构外部的引用。这正是您想要的。然后,只要对它的最后一个外部引用消失,就会回收根,以及递归它的所有子项。