perl – 嵌套闭包和捕获的变量

我有这个带有嵌套闭包的例子,它演示了内存泄漏

use v5.10;
use strict;

package Awesome;

sub new {
    bless {steps => [],surprise => undef},shift;
}

sub say {
    print "awesome: ",$_[1],"\n";
}

sub prepare {
    my ($self,@steps) = @_;

    for my $s (@steps) {
        push @{$self->{steps}},sub {
            $self->say($s);

            if ($s eq 'pony') {
                $self->{surprise} = sub {
                    $s;
                }
            }
        };
    }
}

sub make {
    my $self = shift;

    while (my $step = shift @{$self->{steps}}) {
        $step->();
    }

    if ($self->{surprise}) {
        printf("And you have surprise: %s\n",$self->{surprise}->());
    }
}

sub DESTROY {
    warn "destroying";
}

package main;

my $a = Awesome->new;
$a->prepare('barbie','pony','flash');
$a->make();

我的perl输出

awesome: barbie
awesome: pony
awesome: flash
And you have surprise: pony
destroying at /tmp/t.pl line 43 during global destruction.

而这个“在全局破坏期间”意味着物体不能以正常方式被破坏,因为它有一些循环引用.

但是,唯一的循环引用是由

push @{$self->{steps}},sub {
            $self->say($s);

我们在第一次关闭时使用$self.然后在make()里面我们将删除这些步骤和循环引用.但看起来这个嵌套的封闭与“惊喜”会产生问题.例如,如果我们不将“pony”传递给prepare(),那么输出将如预期的那样好:

awesome: barbie
awesome: flash
destroying at /tmp/t.pl line 43.

那么,perl中的嵌套闭包是否捕获了与已经捕获的上层闭包相同的变量,即使我们没有使用它们?

解决方法

Perl过去常常在嵌套的闭包中过度捕获,但自5.18以来它不会这样做.

$tail -n 9 a.pl   # Modified to make clearer when the object is destroyed.
package main;

{
   my $a = Awesome->new;
   $a->prepare('barbie','flash');
   $a->make();
}

print "done.\n";

 

$5.16.3t/bin/perl a.pl
awesome: barbie
awesome: pony
awesome: flash
And you have surprise: pony
done.
destroying at a.pl line 43 during global destruction.

 

$5.18.2t/bin/perl a.pl
awesome: barbie
awesome: pony
awesome: flash
And you have surprise: pony
destroying at a.pl line 43.
done.

相关文章

1. 如何去重 #!/usr/bin/perl use strict; my %hash; while(...
最近写了一个perl脚本,实现的功能是将表格中其中两列的数据...
表的数据字典格式如下:如果手动写MySQL建表语句,确认麻烦,...
巡检类工作经常会出具日报,最近在原有日报的基础上又新增了...
在实际生产环境中,常常需要从后台日志中截取报文,报文的形...
最近写的一个perl程序,通过关键词匹配统计其出现的频率,让...