【问题标题】:Getting stack traces in Perl? [duplicate]在 Perl 中获取堆栈跟踪? [复制]
【发布时间】:2011-01-22 23:48:31
【问题描述】:

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

【问题讨论】:

  • perl -d script.plDB<1> t 50Trace = on (to level 51)DB<2> T

标签: perl stack-trace


【解决方案1】:

出于调试需要,我喜欢Carp::Always

perl -MCarp::Always my_script.pl

【讨论】:

  • 我好像需要做-MCarp=verbose
【解决方案2】:

Carp::confess(来自use Carp;)将作为错误的一部分为您提供完整的堆栈跟踪。如果你只是需要它作为失败的一部分,confess 就是你真正需要的。

每个 cmets,这里是各种 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 - 在评估之前: longmess 在 - 第 14 行 main::baz 在第 10 行调用 main::bar 在第 6 行调用 main::foo('CODE(0x183a4d0)') 在第 26 行调用 eval {...} 在第 25 行调用 longmess - 之前如果: 长篇大论 - 完成 承认 - 在评估之前: 承认 - 之前如果: 抓到:在第 20 行使用表白 main::__ANON__() 在第 14 行调用 main::baz 在第 10 行调用 main::bar 在第 6 行调用 main::foo('CODE(0x183a3e0)') 在第 26 行调用 eval {...} 在第 25 行调用 承认 - 完成 咯咯 - 在评估之前: 在第 19 行使用咯咯声 main::__ANON__() 在第 14 行调用 main::baz 在第 10 行调用 main::bar 在第 6 行调用 main::foo('CODE(0x183a434)') 在第 26 行调用 eval {...} 在第 25 行调用 咯咯 - 之前如果: 咯咯 - 完成

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

在第 19 行使用咯咯声 main::__ANON__() 在第 14 行调用 main::baz 在第 10 行调用 main::bar 在第 6 行调用 main::foo('CODE(0x183a434)') 在第 26 行调用 eval {...} 在第 25 行调用

【讨论】:

  • 将堆栈跟踪和错误发送到 STDERR;如果需要捕获,直接使用底层的 Carp::longmess()。而 Carp::cluck 就像是认罪,但之后就死了。
  • 我认为这是倒退——cluck 是带有堆栈跟踪的警告,confess 是一个死机。
【解决方案3】:

有许多有用的、基于核心和 CPAN 的工具可以生成堆栈跟踪(如其他答案所示。)但是,如果您想自己动手,请查看 caller 内置工具。您可以使用它沿着堆栈向下走,看看到底发生了什么。

【讨论】:

  • 呃,或者使用Devel::StackTrace
  • 这很好,其他选择。但它需要一个外部模块,它可能会或可能不会吸引人。为什么不把它作为答案发布,而不是投反对票?
  • 您可以在this answer 中找到使用caller 的示例。
【解决方案4】:

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

【讨论】:

    猜你喜欢
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 2016-02-19
    • 2010-09-11
    • 2011-06-01
    • 2016-09-03
    • 2010-12-06
    相关资源
    最近更新 更多