Perl:$SIG {__ DIE__},eval {}和堆栈跟踪
我有一段Perl代码有点像以下(强烈的简化):有一些级别的嵌套子程序调用(实际上是方法),一些内部函数执行自己的异常处理:
sub outer { middle() } sub middle { eval { inner() }; if ( my $x = $@ ) { # caught exception if (ref $x eq 'ARRAY') { print "we can handle this ..."; } else { die $x; # rethrow } } } sub inner { die "OH NOES!" } 现在我想更改代码,以便它执行以下操作: >打印一个完整的堆栈跟踪,每一个例外,“气泡”一直到最外层(子外部).具体来说,堆栈跟踪不应该停在“eval {}”的第一个级别. 现在,我这样做的方法是在外部子程序中安装一个本地化的__DIE__处理程序: use Devel::StackTrace; sub outer { local $SIG{__DIE__} = sub { my $error = shift; my $trace = Devel::StackTrace->new; print "Error: $errorn","Stack Trace:n",$trace->as_string; }; middle(); } [编辑:我犯了一个错误,上面的代码实际上并不像我想要的那样工作,它实际上绕过了中间子句的异常处理.所以我猜这个问题应该是真的:我想要甚么行为吗?] 这是完美的,唯一的问题是,如果我正确地理解文档,它依赖于明确不赞成的行为,即__DIE__处理程序即使是在“eval {}”内也被触发的事实,他们真的不应该. perlvar和perlsub都表示在以后版本的Perl中可能会删除此行为. 有没有另一种方法可以实现这一点,而不依赖于弃用的行为,还是保存依赖,即使文档说不另外? 解决方法
依靠文档所说的任何东西都不推荐使用是不安全的.在未来的版本中,行为可能(并且可能会)会发生变化.依靠不推荐的行为会将您锁定到今天运行的Perl版本中.
不幸的是,我没有看到符合你的标准的方法. “正确”的解决方案是修改内部方法来调用Carp :: confess而不是死,并放置定制的$SIG {__ DIE__}处理程序. use strict; use warnings; use Carp qw'confess'; outer(); sub outer { middle(@_) } sub middle { eval { inner() }; die $@ if $@ } sub inner { confess("OH NOES!") } __END__ OH NOES! at c:tempfoo.pl line 11 main::inner() called at c:tempfoo.pl line 9 eval {...} called at c:tempfoo.pl line 9 main::middle() called at c:tempfoo.pl line 7 main::outer() called at c:tempfoo.pl line 5 由于您还在死亡,您可能不需要将呼叫陷入inner(). (你不在你的例子中,你的实际代码可能有所不同) 在您的示例中,您尝试通过$@返回数据.你不能这样做使用 my $x = eval { inner(@_) }; 代替. (我假设这只是简单的代码足以在这里发布的错误.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |