【发布时间】:2011-04-17 22:46:59
【问题描述】:
如何在 Perl 中完全删除一个包?这不仅意味着包变量,还意味着 Perl 更新以处理继承更改和其他事情的任何魔术表。
这个简单的测试:
use warnings; use strict;
use Test::LeakTrace;
use Symbol 'delete_package';
leaktrace {
package test;
our $x = 1;
package main;
delete_package 'test';
};
产生以下输出:
leaked ARRAY(0x81c930) from /lib/perl5/5.10.1/Symbol.pm line 166.
leaked HASH(0x827760) from /lib/perl5/5.10.1/Symbol.pm line 166.
leaked SCALAR(0x821920) from /lib/perl5/5.10.1/Symbol.pm line 166.
对leaktrace 使用-verbose 标志会产生大量数据,我可以根据要求发布这些数据。
如果将our @ISA = 'main'; 行添加到test 包中,情况会变得更糟:
leaked ARRAY(0x81cd10) from so.pl line 32.
leaked SCALAR(0x81c930) from so.pl line 32.
leaked ARRAY(0x8219d0) from so.pl line 32.
leaked HASH(0x8219c0) from so.pl line 32.
leaked SCALAR(0x8219b0) from so.pl line 32.
leaked HASH(0x8219a0) from so.pl line 32.
leaked SCALAR(0x821970) from /lib/perl5/5.10.1/Symbol.pm line 161.
leaked HASH(0x821950) from so.pl line 32.
leaked SCALAR(0x821940) from so.pl line 32.
第 32 行是 our @ISA 所在的位置。
为了说明这些确实是泄漏,而不仅仅是解释器的噪音:
my $num = 0;
while (1) {
no strict 'refs';
@{$num.'::ISA'} = 'main';
delete_package $num++;
}
会以恒定的速度吃掉内存
那么,有没有比 Symbol 的 delete_package 更好的方法来摆脱包?我还需要做些什么来帮助它吗?
我在 5.8.8、5.10.1 和 5.12 中看到了相同的行为
【问题讨论】:
-
一个很好的问题,我的好奇心被激起了,但我不得不问:为什么?
-
在我的 CPAN 模块
List::Gen(search.cpan.org/perldoc?List::Gen) 中,我有一个实用函数curse,它将基于闭包的对象安装到临时包中(以方便标准方法调用(在高速度))。delete_package清理所有内容,但curse仍然由于上述问题而泄漏内存。泄漏不是很大,但它就在那里,如果可能的话,我想堵住它。 -
如果您还没有,请将其归档为 perl 错误。
-
@ysth => 我刚刚浏览了 RT,发现了几个月前的这个错误报告:rt.perl.org/rt3/Public/Bug/Display.html?id=75176你认为这涵盖了它,还是我应该添加另一个?
标签: perl memory-leaks package