如何在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.
使用-verbose
的{{1}}标记会产生一系列数据,我可以根据要求发布这些数据。
如果将行leaktrace
添加到our @ISA = 'main';
包中,事情会变得更糟:
test
第32行是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.
所在的位置。
为了说明这些确实是泄漏,而不仅仅是解释器的噪音:
our @ISA
会以恒定的速度吃内存
那么,除了符号my $num = 0;
while (1) {
no strict 'refs';
@{$num.'::ISA'} = 'main';
delete_package $num++;
}
之外,还有更好的方法来摆脱一个包吗?还有什么我需要做的来帮助它吗?
我在5.8.8,5.10.1和5.12
中看到过相同的行为答案 0 :(得分:5)
所以这是perl中的一个错误,即使你发现了这个错误。如果没有解决这个问题,那么避免这些泄漏的唯一方法就是选择另一种方法来解决问题。
为什么你需要一个半匿名的包而不是一个闭包?这些很容易使得不会泄漏,并且,通过一些创造性,你仍然可以在它们之上实现几乎所有外部接口,例如通过祝福你的闭包coderefs并为它们提供方法,为它们提供重载等。 / p>