我有一个内存泄漏的脚本 . 我相信这是因为我在嵌套对象上执行 undef
后,脚本中的内存量不变 . 我已经使用Devel::Cycle找到任何循环引用,并且我已经将这些循环引用转换为弱引用 Scalar::Util
. 问题仍然存在 .
现在我试图用Valgrind来解决这个问题 . 作为valgrind的第一个开始,我测试了一个perl hello world程序:
#! /usr/bin/perl
use strict;
use warnings;
print "Hello world!\n";
这是运行 valgrind --trace-children=yes perl ./hello_world.pl
时的valgrind输出:
==12823== HEAP SUMMARY:
==12823== in use at exit: 290,774 bytes in 2,372 blocks
==12823== total heap usage: 5,159 allocs, 2,787 frees, 478,873 bytes allocated
==12823==
==12823== LEAK SUMMARY:
==12823== definitely lost: 13,981 bytes in 18 blocks
==12823== indirectly lost: 276,793 bytes in 2,354 blocks
==12823== possibly lost: 0 bytes in 0 blocks
==12823== still reachable: 0 bytes in 0 blocks
==12823== suppressed: 0 bytes in 0 blocks
==12823== Rerun with --leak-check=full to see details of leaked memory
==12823==
==12823== For counts of detected and suppressed errors, rerun with: -v
==12823== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
我的理解,从here,是当 allocs
的数量不等于 frees
的数量时,你有内存泄漏 .
因为我正在做的就是打印你好世界,我不得不问这个问题,Perl解释器本身,这里是v5.10.1,至少有自己的内存泄漏,还是我解释的都是错的?
在我解决实际的perl脚本之前,我想了解这一点 .
ADDENDUM
我在Perl 5.12.0 delta中看到,如下:
对哈希的弱引用会泄漏 . 这影响了DBI [RT#56908] .
这可能最终适用于我的完整perl脚本,而不是这个hello world程序,但它让我觉得我应该经历安装最新版本的perl作为非root用户的痛苦 .
ADDENDUM2
我安装了activestate perl 5.16.3,问题以及我实际脚本的问题仍然存在 .
我怀疑在这个hello world程序的情况下,我必须使用/解释valgrind不正确,但我还不明白 .
UPDATE1 达西姆的回答确实有所作为 . 当我在perl脚本中引入以下行时:
use Perl::Destruct::Level level => 1;
然后valgrind输出是:
==29719== HEAP SUMMARY:
==29719== in use at exit: 1,617 bytes in 6 blocks
==29719== total heap usage: 6,499 allocs, 6,493 frees, 585,389 bytes allocated
==29719==
==29719== LEAK SUMMARY:
==29719== definitely lost: 0 bytes in 0 blocks
==29719== indirectly lost: 0 bytes in 0 blocks
==29719== possibly lost: 0 bytes in 0 blocks
==29719== still reachable: 1,617 bytes in 6 blocks
==29719== suppressed: 0 bytes in 0 blocks
==29719== Rerun with --leak-check=full to see details of leaked memory
==29719==
==29719== For counts of detected and suppressed errors, rerun with: -v
==29719== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
这是一个实质性的差异 . 我自己的内存泄漏问题仍然存在,但至少这个hello world程序现在对valgrind来说似乎是明智的 .
这一切虽然引出了一个问题,如果在程序退出之前没有释放内存,那么用 Scalar::Util
停止硬循环引用的重点是什么,禁止使用这个有点深奥的 Perl::Destruct::Level
模块???
2 回答
泄漏是故意的 . vincent in #p5p评论:
据我所知(如果我错了请纠正我 - 我没有阅读代码,文档似乎很少),重点是,在一个典型的Perl程序中,有很多东西会是已分配但在程序结束前不会被释放 . 这包括全局变量之类的东西,但也包括编译的程序代码本身 .
现在,perl可以在程序结束时释放用于所有内容的内存,但事实证明在程序结束时还有任何未提及的内存,并且假设任何此类内存必须已泄露 .
因此,基本上,perl通常是懒惰的,当它知道它即将退出并让操作系统处理它时,它不会打扰释放内存 . 设置PERL_DESTRUCT_LEVEL告诉perl无论如何都要清理那个内存,只是为了向valgrind显示它实际上没有被泄露的工具 .
无论如何,AFAIK都不会影响程序执行期间的内存管理 . 如果在释放时将某些内容的引用计数减少为零,则无论PERL_DESTRUCT_LEVEL如何 .
但是请注意,这通常只释放内存以供perl本身重用 - 除了一些罕见的情况,如显式mmap(),在具有虚拟内存的现代操作系统上运行的任何程序实际上将内存页面释放回操作系统是很不寻常的当它在运行 .