在Perl中获取堆栈跟踪?

时间:2010-03-02 23:43:16

标签: perl stack-trace

如何在Perl中获取堆栈跟踪?

4 个答案:

答案 0 :(得分:33)

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 - before eval:
longmess at - line 14
        main::baz called at - line 10
        main::bar called at - line 6
        main::foo('CODE(0x183a4d0)') called at - line 26
        eval {...} called at - line 25
longmess - before if:
longmess - done

confess - before eval:
confess - before if:
caught: using confess at - line 20
        main::__ANON__() called at - line 14
        main::baz called at - line 10
        main::bar called at - line 6
        main::foo('CODE(0x183a3e0)') called at - line 26
        eval {...} called at - line 25
confess - done

cluck - before eval:
using cluck at - line 19
        main::__ANON__() called at - line 14
        main::baz called at - line 10
        main::bar called at - line 6
        main::foo('CODE(0x183a434)') called at - line 26
        eval {...} called at - line 25
cluck - before if:
cluck - done

运行此脚本但重定向STDOUT(从而显示在STDERR上打印的内容),您得到:

using cluck at - line 19
        main::__ANON__() called at - line 14
        main::baz called at - line 10
        main::bar called at - line 6
        main::foo('CODE(0x183a434)') called at - line 26
        eval {...} called at - line 25

答案 1 :(得分:32)

对于调试需求,我喜欢Carp::Always

perl -MCarp::Always my_script.pl

答案 2 :(得分:16)

有许多有用的,基于核心和基于CPAN的工具来生成堆栈跟踪(正如其他答案所示)。但是,如果你想自己推出,请查看caller内置版。您可以使用它来向下走,看看究竟发生了什么。

答案 3 :(得分:9)

使用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";
}