perl - 如何在长时间运行的 Perl 程序中发现内存泄漏?

标签 perl memory-leaks garbage-collection

Perl 使用引用计数进行 GC,很容易意外地产生循环引用。我发现我的程序似乎使用了越来越多的内存,几天后它可能会溢出。

有什么方法可以调试 Perl 中的内存泄漏吗?附加到程序并获取各种类型的对象数量将是一个好的开始。如果我知道哪些对象比预期的数量多得多,我可以检查对它们的所有引用并希望修复泄漏。

最佳答案

Perl 永远不会自行将内存返还给系统,这可能是相关的:这完全取决于 malloc() 以及与之相关的所有规则。

了解malloc()如何分配内存对于回答更大的问题很重要,并且它因系统而异,但一般来说大多数malloc()实现都是优化的用于以类似堆栈的顺序分配和取消分配的程序。 Perl 使用引用计数来跟踪内存,这意味着释放意味着(与底层使用 malloc() 的基于 GC 的语言不同)实际上并不那么难告诉 释放将在哪里发生以及以什么顺序发生。

您可能可以重新组织您的程序以利用这一事实 - 通过显式调用 undef($old_object) - 以正确的顺序,以类似于 C 的方式 -程序员说free(old_object);

对于长时间运行的程序(几天、几个月等),我有大量的加载/复制/转储周期,我使用 exit() 和 exec() 进行垃圾收集,并且在哪里这是不可行的,我只是打包我的数据结构(使用 Storable)和文件描述符(使用 $^F)和 exec($0) - 通常使用像 $ENV{EXEC_GC_MODE} 这样的环境变量设置,即使您自己没有任何泄漏,您也可能需要类似的东西,因为 Perl 是泄漏系统 malloc() 无法弄清楚如何归还的小块。

当然,如果您的代码确实存在泄漏,那么我的其余建议会更相关。最初发布于to another question on this subject ,但它没有明确涵盖长时间运行的程序。

<小时/>

所有 Perl 程序内存泄漏要么是 XS 持有引用,要么是循环数据结构。 Devel::Cycle如果您知道哪些结构可能包含循环,那么它是查找循环引用的好工具。 Devel::Peek可用于查找引用计数高于预期的对象。

如果您不知道还能去哪里查看,Devel::LeakTrace::Fast可能是一个不错的首选,但您需要构建一个用于调试的 perl。

如果你怀疑泄漏是在 XS 空间内部,那就更难了,并且 Valgrind可能会是您最好的选择。 Test::Valgrind可能会帮助您减少需要搜索的代码量,但这在 Windows 上不起作用,因此您必须将(至少是泄漏部分)移植到 Linux 才能做到这一点。

关于perl - 如何在长时间运行的 Perl 程序中发现内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/429254/

相关文章:

java - 为什么会发生 Full GC Continuous?

regex - 如何在 perl 中将字符串的字母和数字分开?

perl - 使用 perl 从 http 帖子中获取/转储所有信息

c++ - SDL_Init 中的大内存泄漏

c pthreads + valgrind = 内存泄漏 : why?

Java 类 (PermGen) 内存泄漏(Web 应用程序)- 通用解决方案?

javascript - JS垃圾收集器会清除堆栈内存吗?

Perl - 有没有办法用一些文本框显示通知?

regex - 如何使用正则表达式查找不属于某种模式的东西

javascript - 未安装组件的状态更新如何导致内存泄漏?