Eri*_*rom 27 perl memory-leaks package
你如何完全删除Perl中的包?这不仅意味着包变量,还意味着Perl更新以处理继承更改和其他事物的任何魔术表.
这个简单的测试:
use warnings; use strict;
use Test::LeakTrace;
use Symbol 'delete_package';
leaktrace {
package test;
our $x = 1;
package main;
delete_package 'test';
};
Run Code Online (Sandbox Code Playgroud)
得到以下输出:
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.
Run Code Online (Sandbox Code Playgroud)
使用该-verbose标志来leaktrace显示我可以根据请求发布的数据屏幕.
如果将行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.
Run Code Online (Sandbox Code Playgroud)
第32行就是这样our @ISA.
为了说明这些确实是泄漏而不仅仅是解释器的噪音:
my $num = 0;
while (1) {
no strict 'refs';
@{$num.'::ISA'} = 'main';
delete_package $num++;
}
Run Code Online (Sandbox Code Playgroud)
会以恒定的速度吃记忆
那么,有没有比Symbol更好的摆脱包装的方法delete_package呢?我还需要做些什么来帮助它吗?
我在5.8.8,5.10.1和5.12中看到过相同的行为
所以这是perl中的一个错误,即使你发现了这个错误.如果没有解决这个问题,那么避免这些泄漏的唯一方法就是选择另一种方法来解决问题.
你怎么需要一个半匿名的包而不是一个闭包呢?这些都很容易使得不会泄漏,而且,通过一些创造性,你仍然可以在它们之上实现几乎所有的外部接口,例如通过祝福你的闭包coderefs并为它们提供方法,为它们提供重载等.