这个纯Perl编程示例怎么会泄漏?

这个纯Perl编程示例怎么会泄漏?,perl,function,memory,recursion,memory-leaks,Perl,Function,Memory,Recursion,Memory Leaks,我最近一直在对一个特别粗糙的递归X执行一些泄漏检查,当我成功地使所有引用计数工作正常时,我感到非常高兴 想象一下,当我在一个相对良性的纯Perl中发现漏洞时,我的震惊 有谁能告诉我为什么这个看似无害的递归函数会像疯了一样泄漏?(Linux,Ubuntu 12.10,64位) 怎么回事 什么是您的perl-V?在win32 citrusperl v5.16.1上它不会泄露给我,如果我可以评论,这将是一个评论:) 更新:这是代码,更改循环量,更改数据结构的大小,它不会增长 #!/usr/bin/pe

我最近一直在对一个特别粗糙的递归X执行一些泄漏检查,当我成功地使所有引用计数工作正常时,我感到非常高兴

想象一下,当我在一个相对良性的纯Perl中发现漏洞时,我的震惊

有谁能告诉我为什么这个看似无害的递归函数会像疯了一样泄漏?(Linux,Ubuntu 12.10,64位)


怎么回事

什么是您的
perl-V
?在win32 citrusperl v5.16.1上它不会泄露给我,如果我可以评论,这将是一个评论:)

更新:这是代码,更改循环量,更改数据结构的大小,它不会增长

#!/usr/bin/perl --
use strict;
use warnings;
use Devel::Leak;

sub annotated_hex {
    my $annotated = shift;
    if (ref $annotated ne 'HASH') { return '<' . (ref $annotated) . '>'; }

    my $hex = '';
    if (defined $annotated->{hex}) {
        $hex .= $annotated->{hex};
    }
    if (defined $annotated->{elements}) {
        if (ref $annotated->{elements} eq 'ARRAY') {
            foreach my $element (@{ $annotated->{elements} }) {
                $hex .= &annotated_hex ($element);
            }
        } else {
            $hex .= '<Elements=' . (ref $annotated->{elements}) . '>';
        }
    }        
    return $hex;
}

for(1..100){
    print ' ', Devel::Leak::NoteSV (my $handle);
    my $annotated = {
        'hex' => 'a824',
        'elements' => [
            map {; { 'hex' => '0201'.$_ } } 1 .. ( 100*$_ )
        ],
    };

    my $annotated_hex = &annotated_hex ($annotated);

    undef $annotated_hex;
    undef $annotated;
    print ' ', Devel::Leak::CheckSV ($handle);
}
1;
__END__
new 009EC17C :
new 009EC1AC :
new 009DF6CC :
new 009DF89C :
new 009DFC8C :
new 009AAAE4 :
new 009AAD04 :
new 009AAFB4 :
new 0099AEF4 :
new 0099AF04 :
new 0099AF14 :
new 0099AF24 :
new 0099AF84 :
new 0099AF94 :
new 0099AFD4 :
new 0099AFE4 :
new 0099AFF4 :
new 0099B4A4 :
new 0099B604 :
new 003F915C :
new 003F916C :
new 003F91AC :
new 003F91CC :
new 003F91FC :
 2256 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280
#/usr/bin/perl--
严格使用;
使用警告;
使用Devel::Leak;
子注释_十六进制{
my$annotated=shift;
if(ref$annotated ne'HASH'){return';}
我的$hex='';
if(定义为$annotated->{hex}){
$hex.=$annotated->{hex};
}
if(已定义$annotated->{elements}){
if(ref$annotated->{elements}eq'ARRAY'){
foreach my$元素(@{$annotated->{elements}){
$hex.=&带注释的_hex($element);
}
}否则{
$hex.='';
}
}        
返回$hex;
}
对于(1..100){
打印“”,Devel::Leak::NoteSV(我的$handle);
my$annotated={
“十六进制”=>“a824”,
“元素”=>[
映射{;{'hex'=>'0201'.$\u}}}1..(100*$\u1)
],
};
my$annotated_hex=&annotated_hex($annotated);
未定义$带注释的_十六进制;
未定义$加注释;
打印“”,Devel::Leak::CheckSV($handle);
}
1.
__结束__
新的009EC17C:
新的009EC1AC:
新009DF6CC:
新的009DF89C:
新的009DFC8C:
新009AAAE4:
新009AAD04:
新009AAFB4:
新0099AEF4:
新0099AF04:
新0099AF14:
新0099AF24:
新0099AF84:
新0099AF94:
新0099AFD4:
2009年2月4日新增:
新0099AFF4:
新0099B4A4:
新0099B604:
新003F915C:
新003F916C:
新003F91AC:
新003F91CC:
新003F91FC:
2256 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
2280 2280 2280 2280 2280 2280 2280 2280

我不确定“泄漏”这个词在这里是否合适。我通过多次调用
annotated_hex
并使用多个不同的散列引用和字符串来扩展您的示例,并且从
CheckSV
返回的新元素总数始终比
NoteSV
中的新元素总数多25个


换句话说,泄漏并没有增加。我怀疑25来自于在评估函数时根据需要创建的一些新的内部perl引用。

nit:为什么要用
&
调用函数?我真的不认为这是问题所在,但您似乎也不需要它们(颠覆原型)不,它不会影响泄漏($perl-v=“这是为x86_64-linux-gnu-thread-multi构建的perl 5,版本14,subversion 2(v5.14.2)”(perl-v有点太大了,不能放在评论中)!但是
perl-v
对于您的帖子来说不是太大——尽管我认为它不是必需的,但我已经更新了我的帖子
$ perl annotate.pl 
new 0x22d8a80 : SV = NULL(0x0) at 0x22d8a80
  REFCNT = 1
  FLAGS = (PADMY)
new 0x22d8f78 : SV = NULL(0x0) at 0x22d8f78
...[24 leaked entries in total]
#!/usr/bin/perl --
use strict;
use warnings;
use Devel::Leak;

sub annotated_hex {
    my $annotated = shift;
    if (ref $annotated ne 'HASH') { return '<' . (ref $annotated) . '>'; }

    my $hex = '';
    if (defined $annotated->{hex}) {
        $hex .= $annotated->{hex};
    }
    if (defined $annotated->{elements}) {
        if (ref $annotated->{elements} eq 'ARRAY') {
            foreach my $element (@{ $annotated->{elements} }) {
                $hex .= &annotated_hex ($element);
            }
        } else {
            $hex .= '<Elements=' . (ref $annotated->{elements}) . '>';
        }
    }        
    return $hex;
}

for(1..100){
    print ' ', Devel::Leak::NoteSV (my $handle);
    my $annotated = {
        'hex' => 'a824',
        'elements' => [
            map {; { 'hex' => '0201'.$_ } } 1 .. ( 100*$_ )
        ],
    };

    my $annotated_hex = &annotated_hex ($annotated);

    undef $annotated_hex;
    undef $annotated;
    print ' ', Devel::Leak::CheckSV ($handle);
}
1;
__END__
new 009EC17C :
new 009EC1AC :
new 009DF6CC :
new 009DF89C :
new 009DFC8C :
new 009AAAE4 :
new 009AAD04 :
new 009AAFB4 :
new 0099AEF4 :
new 0099AF04 :
new 0099AF14 :
new 0099AF24 :
new 0099AF84 :
new 0099AF94 :
new 0099AFD4 :
new 0099AFE4 :
new 0099AFF4 :
new 0099B4A4 :
new 0099B604 :
new 003F915C :
new 003F916C :
new 003F91AC :
new 003F91CC :
new 003F91FC :
 2256 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280
 2280 2280 2280 2280 2280 2280 2280 2280