【问题标题】:How can this Pure Perl programming example be leaking?这个纯 Perl 编程示例怎么会泄露?
【发布时间】:2013-04-23 20:01:03
【问题描述】:

我最近对一个特别粗糙的递归 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]

这是怎么回事?!

【问题讨论】:

  • nit:你为什么用&amp; 调用你的函数?我真的不认为这是问题所在,但您似乎也不需要它们(颠覆原型)。
  • 习惯的力量,我从 Perl 4 开始。:) 不,它不会影响泄漏。 :(

标签: perl function memory recursion memory-leaks


【解决方案1】:

你的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

【讨论】:

  • $ perl -v = "这是为 x86_64-linux-gnu-thread-multi 构建的 perl 5,版本 14,subversion 2 (v5.14.2)"(perl -V 有点太大了发表评论)!
  • 但是perl -V 对你的帖子来说不是太大——虽然我认为它不是必需的,但我已经更新了我的帖子
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2013-08-01
    • 2011-05-02
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 2012-01-30
    相关资源
    最近更新 更多