Perl die()调用神秘地没有消亡

  • 本文关键字:die 调用 Perl perl eval die
  • 更新时间 :
  • 英文 :


在对项目中一个非常模糊的bug进行了一些认真的调试之后,我能够获得这段简短的代码。一个没有死亡的死亡召唤。

只有在调用script.pl时才会出现此问题。如果直接调用Class_A,则die调用将成功。

我们需要三个文件:

文件1:script.pl

use strict;
use warnings;
use lib '.';
use Class_A;
# This should not execute. Class_A should die at loading time
print "We shouldn't get here. Class_A shoud not load and die.n";

文件2:Class_A.pm

package Class_A;
use strict;
use warnings;
use Class_B;
# This code SHOULD die:
my $p = Class_B->new;
$p->do_something->die_now;

1;

文件3:Class_B.pm

package Class_B;
use strict;
use warnings;
sub new {
my $class = shift;
bless {}, $class;
}
sub do_something {
my $self = shift;
}
sub die_now {
die "No soup for you!";
}
sub DESTROY {
eval {
1;
};
}
1;

注意到链式调用at Class_A.pm line 8了吗?好吧,如果你取消捕获它,那么代码就会成功消亡。:-|

# This works. There should be no difference.
$p->do_something;
$p->die_now;

最后一个惊喜是发现只需删除eval调用at Class_B.pm line 19,事情就会如预期那样运行,脚本就会失效。

我有机会在Perl 5.22.2Perl 5.26.1Perl 5.32.0中对此进行了测试。另一个惊喜是,这个问题不仅仅发生在5.32.0上。

说真的,WT*?有什么想法吗?

您发布的代码自5.28以来就没有出现问题。

该问题与$@在因异常而发生的放卷过程中(使用eval { }(受到撞击有关。显然,取消设置$@欺骗了Perl,使其认为不会出现任何异常。

根据perl528delta,$@现在是在所有东西都被破坏后设置的,这防止了析构函数对$@的破坏。您还可以通过添加local $@;(例如,支持旧版本的Perl(来防止析构函数破坏$@

最新更新