我如何在Perl中获取堆栈跟踪?
为了调试需求,我喜欢使用Carp::Always。
perl -MCarp::Always my_script.pl
Carp::confess
(来自 use Carp;
)可以作为错误的一部分提供完整的堆栈跟踪。如果你只需要作为失败的一部分,confess
就足够了。
根据评论,以下是各种 Carp
函数的输出:
use strict;
use warnings;
use Carp qw/longmess cluck confess/;
sub foo {
&bar;
}
sub bar {
&baz;
}
sub baz {
shift->();
}
my %tests = (
'longmess' => sub { print longmess 'longmess' },
'cluck' => sub { cluck 'using cluck' },
'confess' => sub { confess 'using confess' },
);
while (my ($name, $sub) = each %tests) {
print "$name - before eval:\n";
eval {
foo($sub);
};
print "$name - before if:\n";
if ($@) {
print "caught: $@";
}
print "$name - done\n\n";
}
运行此脚本,您会得到:
longmess - 在 eval 之前: longmess 在 - 第 14 行 main::baz 被调用于 - 第 10 行 main::bar 被调用于 - 第 6 行 main::foo('CODE(0x183a4d0)') 被调用于 - 第 26 行 eval {...} 被调用于 - 第 25 行 longmess - 在 if 之前: longmess - 完成
confess - 在 eval 之前: confess - 在 if 之前: caught: using confess at - 第 20 行 main::__ANON__() 被调用于 - 第 14 行 main::baz 被调用于 - 第 10 行 main::bar 被调用于 - 第 6 行 main::foo('CODE(0x183a3e0)') 被调用于 - 第 26 行 eval {...} 被调用于 - 第 25 行 confess - 完成
cluck - 在 eval 之前: using cluck at - 第 19 行 main::__ANON__() 被调用于 - 第 14 行 main::baz 被调用于 - 第 10 行 main::bar 被调用于 - 第 6 行 main::foo('CODE(0x183a434)') 被调用于 - 第 26 行 eval {...} 被调用于 - 第 25 行 cluck - 在 if 之前: cluck - 完成
运行此脚本但将 STDOUT 重定向(因此显示在 STDERR 上的内容),您会得到:
using cluck at - 第 19 行 main::__ANON__() 被调用于 - 第 14 行 main::baz 被调用于 - 第 10 行 main::bar 被调用于 - 第 6 行 main::foo('CODE(0x183a434)') 被调用于 - 第 26 行 eval {...} 被调用于 - 第 25 行
cluck
是带有堆栈跟踪的警告,而 confess
是死亡。 - mob使用caller
的简单方法。
此代码不使用任何额外模块,只需在需要的地方包含即可。
my $i = 1;
print "Stack Trace:\n";
while ( (my @call_details = (caller($i++))) ){
print $call_details[1].":".$call_details[2]." in function ".$call_details[3]."\n";
}
$call_details[1].":".$call_details[2]
(呼叫者)和$call_details[3]
(被呼叫者)更合理。 - zb226
perl -d script.pl
DB<1> t 50
Trace = on (to level 51)
DB<2> T
- nurp