Perl 自动管理内存:当没有对变量的引用时,变量会被销毁(引用计数)。Perl 的垃圾收集器 不使用 典型的追踪垃圾收集机制,而是依赖于引用计数。
优点:
free())。缺点和陷阱:
my $a = {}; my $b = {}; $a->{b} = $b; $b->{a} = $a; # 两个变量在清理时都不会被释放,perl 无法删除它们
为了解决此类问题,使用模块 Scalar::Util::weaken,它可以“减弱”引用:
use Scalar::Util 'weaken'; my $a = {}; my $b = {}; $a->{b} = $b; weaken($b->{a} = $a);
在删除对 Perl 中的所有显式变量的引用时,任何对象会被销毁吗,即使内部有引用相互指向?
回答: 不会!如果对象相互引用(形成循环),Perl 不会将其删除 — 需要手动打破循环或通过 Scalar::Util::weaken 减弱引用。
故事
在开发一个长期运行的守护进程,处理大量连接时,程序员没有注意到 IoHandle 对象与相关事件处理程序之间的循环引用。经过几个小时的工作,内存以指数速度增长 — 只有通过 Devel::Leak 分析才揭示了问题。
故事
在解析大文件的 ETL 过程中,数百万个临时哈希元素的累积导致进程“挂起”,即使在循环结束后。因为其中一个元素存储了对父级的嵌套引用(用于三级连接),导致内存没有被释放。部分重构架构帮助避免了泄漏。
故事
程序员在 MapReduce 引擎中使用闭包,将上下文副本保存在匿名子程序中。这些子程序“泄漏” — 内存即使在批处理任务结束后也没有被释放,因为上下文包含对自身的引用。添加了显式的
undef以正确销毁。