解决方法
sub leak { my ($foo,$bar); $foo = \$bar; $bar = \$foo; }
Perl使用引用计数垃圾收集.这意味着perl在给定的时间内保留对任何变量的指针的计数.如果变量超出范围并且计数为0,则该变量被清除.
在上面的示例代码中,$foo和$bar不会被收集,每次调用leak()后都会保留一个副本,因为这两个变量的引用次数都为1.
防止这个问题的最简单方法是使用弱引用.弱引用是您访问数据时引用的引用,但不计入垃圾回收.
use Scalar::Util qw(weaken); sub dont_leak { my ($foo,$bar); $foo = \$bar; $bar = \$foo; weaken $bar; }
在dont_leak()中,$foo的引用计数为0,$bar的引用计数为1.当我们离开子例程的范围时,$foo将返回到池中,并且其对$bar的引用被清除.这将$bar上的引用计数值降至0,这意味着$bar也可以返回到池中.
更新:
大脑d foy问我是否有任何数据来备份我的断言,循环引用是常见的.不,我没有任何统计资料显示循环引用是常见的.它们是perl内存泄漏最常见的和最好的记录形式.
我的经验是他们确实发生.对于在Perl中工作十年的内存泄漏来说,这是一个很快的破坏.
我有pTk应用程序开发漏洞的问题.有些漏洞我能证明是由于循环引用,当Tk通过窗口引用时出现.我也看过pTK泄漏,其原因我无法追踪.
我已经看到人们的误解减弱了,意外的结果是循环引用.
我曾经看到无意间的周期出现,当太多思想深思的对象被匆匆扔在一起时.
有一次,我发现来自XS模块的内存泄漏,这个XS模块正在创建大量,深入的数据结构.我从来没有能够获得比整个程序小的可重复测试用例.但是当我用另一个串行器替换模块时,泄漏就消失了.所以我知道这些泄漏来自XS.
所以,在我的经验周期是泄漏的主要来源.
幸运的是,there is a module帮助跟踪他们.
关于从未被清理的大型全球性结构是否构成“泄漏”,我同意布莱恩.他们像泄漏一样qu s(由于一个bug,我们的进程内存使用量不断增长),所以它们是泄漏的.即使如此,我也不记得在野外看到这个特殊的问题.
根据我在Stonehenge网站上看到的内容,我猜Brian看到他正在训练或提出治愈奇迹的人的很多病态代码.所以他的样本集容易比我的更大和更多,但它有自己的选择偏见.
哪些泄漏原因最常见?我不认为我们真的会知道.但是我们都同意循环引用和全局数据垃圾场是反模式,需要在可能的情况下被消除,并且在少数情况下应该小心谨慎处理.