在对项目中一个非常模糊的错误进行了一些认真的调试之后,我能够得到这个简短的代码。一个没有死亡的死亡呼叫。
该问题仅在调用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";
Run Code Online (Sandbox Code Playgroud)
文件 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;
Run Code Online (Sandbox Code Playgroud)
文件 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;
Run Code Online (Sandbox Code Playgroud)
注意到链式调用了at Class_A.pm line 8吗?好吧,如果你解开它,那么代码就会成功终止。:-|
# This works. There should be no difference.
$p->do_something;
$p->die_now;
Run Code Online (Sandbox Code Playgroud)
而且,最后一个惊喜是发现仅仅通过删除 eval 调用 at Class_B.pm line 19,然后事情按预期工作并且脚本死了。
我有机会在Perl 5.22.2,Perl 5.26.1和 中对此进行测试Perl 5.32.0。另一个奇妙的惊喜是,这个问题不仅仅发生在5.32.0。
说真的,WT*?对这里发生的事情有什么想法吗?
ike*_*ami 10
您发布的代码从 5.28 开始就没有出现问题。
问题涉及在因异常而发生的展开期间$@被破坏(使用eval { })。显然,$@让 Perl误以为没有异常发生。
根据 perl528delta,$@现在在一切都被销毁后设置,这可以防止析构函数破坏$@. 您还可以$@通过添加local $@;(例如支持旧版本的 Perl)来防止析构函数被破坏。