2

我最近一直在对一个特别粗糙的递归 XS 进行一些泄漏检查,当我设法让我的所有引用计数工作得很好时,我感到非常高兴。

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

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

#!/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;
}

Devel::Leak::NoteSV (my $handle);
my $annotated = { 'hex' => 'a824', 'elements' => [ { 'hex' => '0201', }, ] };
my $annotated_hex = &annotated_hex ($annotated);

undef $annotated_hex;
undef $annotated;
Devel::Leak::CheckSV ($handle);
1;

输出有很多泄漏...

$ 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]

那是怎么回事?!

4

2 回答 2

0

你的是什么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
于 2013-04-30T13:00:26.577 回答
0

我不确定“泄漏”是在这里使用的正确词。我通过多次调用annotated_hex和使用多个不同的哈希引用和字符串来扩充您的示例,并且从返回的新元素的总数CheckSV总是比NoteSV

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

于 2013-04-30T13:52:17.003 回答