Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 从一个匿名子系统递归调用另一个匿名子系统安全吗?_Perl_Mason - Fatal编程技术网

Perl 从一个匿名子系统递归调用另一个匿名子系统安全吗?

Perl 从一个匿名子系统递归调用另一个匿名子系统安全吗?,perl,mason,Perl,Mason,我之所以想使用匿名子组件而不是命名子组件,是因为我想在Mason subcomponents()中定义这些子组件,而Mason subcomponents()在命名子组件中表现不佳 例如,如果我以这种方式编写代码: my ($first, $second); $first = sub { my $val = shift; print "val: $val"; $second->($val); }; $second = sub { my $val = shif

我之所以想使用匿名子组件而不是命名子组件,是因为我想在Mason subcomponents()中定义这些子组件,而Mason subcomponents()在命名子组件中表现不佳

例如,如果我以这种方式编写代码:

my ($first, $second);
$first = sub {
    my $val = shift;
    print "val: $val";
    $second->($val);
};
$second = sub {
    my $val = shift;
    if (0 < $val) {
        $val = $val - 1;
        $first->($val);
    }
};
$first->(10);
my($first,$second);
$first=sub{
我的$val=班次;
打印“val:$val”;
$second->($val);
};
$second=sub{
我的$val=班次;
如果(0<$val){
$val=$val-1;
$first->($val);
}
};
$first->(10);
这种方法是否存在任何隐藏的漏洞(例如内存泄漏等)

正如@Schwern所解释的,Perl不会释放这些sub的内存,因为它们之间有一个循环引用


但更具体地说,内存分配会随着$val的增加而线性增长,还是不依赖于调用堆栈深度?因为我可以将这些sub放在mason块中,在这种情况下,这些sub将只初始化一次。

以下情况就可以了:

sub first {
    my $val = shift;
    print "val: $val";
    second($val);
}

sub second {
    my $val = shift;
    if (0 < $val) {
        $val = $val - 1;
        first($val);
    }
}

first(10);

解决方案取决于您决定首先使用anon subs的原因。

我唯一能想到的是,即使
$first
$second
超出范围,子例程也永远不会被释放
$first
的代码指的是
$second
$second
的代码指的是
$first
。这是一个循环数据结构,Perl的内存分配不能取消分配

$ perl -wlE 'for (1..10_000) { my($first, $second); $first = sub {};  $second = sub {} } say "Done"; sleep 1000'

$ perl -wlE 'for (1..10_000) { my($first, $second); $first = sub { $second->() }; $second = sub { $first->() } } say "Done"; sleep 1000'
第一个Perl进程在循环后使用1912K,第二个使用10320K。无论创建多少CV,第一个CV都不会增长,第二个CV将增长

要解决这个问题,您必须通过取消定义
$first
$second
来打破循环。第三个在循环中调用
undef$first
,其内存不会增长

$ perl -wlE 'for (1..100_000) { my($first, $second); $first = sub { $second->() }; $second = sub { $first->() }; undef $first; } say "Done"; sleep 1000'

谢谢大家!但基本上,如果我在循环之外定义匿名子循环,我的内存占用不会增加?循环只会夸大问题;您仍然必须取消定义$first或$second函数以避免循环结构。@Yakov循环仅用于说明泄漏。它A)提供了一个词法上下文(即块),子例程在退出时会被破坏;B)夸大了内存泄漏,因此它会出现在一个粗糙的工具中,如
ps
@Yakov,如果代码不在某种循环中,那么很难想象为什么需要一个子例程。同样的道理,如果需要anon潜艇,那么Schwern释放它们的解决方案可能无法使用。
$ perl -wlE 'for (1..10_000) { my($first, $second); $first = sub {};  $second = sub {} } say "Done"; sleep 1000'

$ perl -wlE 'for (1..10_000) { my($first, $second); $first = sub { $second->() }; $second = sub { $first->() } } say "Done"; sleep 1000'
$ perl -wlE 'for (1..100_000) { my($first, $second); $first = sub { $second->() }; $second = sub { $first->() }; undef $first; } say "Done"; sleep 1000'