Perl使用GC的引用计数,并且很容易意外地进行循环引用.我看到我的程序似乎使用了越来越多的内存,并且它可能会在几天后溢出.
有没有办法在Perl中调试内存泄漏?附加到程序并获取各种类型的对象将是一个良好的开端.如果我知道哪些对象比预期的要多得多,我可以检查所有对它们的引用并希望修复泄漏.
可能有必要的是,Perl 永远不会将内存返回给系统:它完全取决于malloc()
与之相关的所有规则.
了解如何malloc()
分配内存对于回答更大的问题非常重要,并且它因系统而异,但通常大多数malloc()
实现都针对在堆栈类订单中分配和解除分配的程序进行了优化.Perl使用引用计数来跟踪内存,这意味着解除分配意味着(与使用底层的基于GC的语言不同malloc()
)实际上并不是很难分辨释放将在何处发生,以及按什么顺序排列.
可能是您可以重新组织您的程序以利用这一事实 - 通过undef($old_object)
明确调用- 并以正确的顺序,以类似于C程序员所说的方式free(old_object);
对于长时间运行的程序(天,月等),我有大量的加载/复制/转储循环,我使用垃圾收集exit() and exec()
,并且在其他地方不可行的地方,我只是打包我的数据结构(使用Storable
)和文件描述符(使用$^F
)和exec($0)
- 通常使用环境变量设置$ENV{EXEC_GC_MODE}
,你可能需要类似的东西,即使你没有自己的任何泄漏只是因为Perl正在泄漏小块,你的系统malloc()
无法弄清楚如何回馈.
当然,如果您的代码确实存在泄漏,那么我的其他建议会更加相关.它最初发布在关于这个主题的另一个问题上,但它没有明确涵盖长期运行的程序.
所有perl程序内存泄漏都将是保存在引用上的XS,或者是循环数据结构.如果您知道哪些结构可能包含循环,则Devel :: Cycle是查找循环引用的绝佳工具.Devel :: Peek可用于查找引用计数高于预期的对象.
如果你不知道在哪里看,Devel :: LeakTrace :: Fast可能是一个很好的第一名,但是你需要一个用于调试的perl.
如果你怀疑泄漏是在XS空间内,那就更难了,Valgrind可能是你最好的选择.Test :: Valgrind可以帮助您减少搜索所需的代码量,但这不适用于Windows,因此您必须将(至少泄漏部分)移植到Linux才能执行此操作.
Devel :: Gladiator是这个领域的另一个有用的工具.