我可以让Perl删除堆栈帧吗?

时间:2012-11-08 00:37:38

标签: perl stack-trace

我最近一直在研究一些代码来捕获整个代码库中的错误(I.E.在我们的Perl代码的最顶层做一个try / catch)。令我痛苦的是,我发现Perl堆栈跟踪忽略了堆栈帧! GAAA!我正在寻找洞察这些堆栈帧消失的原因。 caller()的文档说堆栈帧可以“优化掉”。但实际上,让它们消失是如此烦人。有没有办法哄Perl包含它们?这样做有性能损失吗?以下是一个简单的例子。正如您将看到的,堆栈跟踪中既不包含bar()也不包含bletch()。遗憾的遗漏导致我必须手工追踪代码。

感激地收到任何见解。

伦纳德

这是foo.pl

use strict;
use warnings;

use Devel::StackTrace;
use Try::Tiny;

foo();

sub foo {
    print "In foo\n";
    try {
        bar();
    }
    catch {
        my $trace = Devel::StackTrace->new();
        print $trace->as_string;
    };
}

sub bar {
    print "In bar\n";
    bletch();
    my $more_stuff = 123;
    return $more_stuff;
}

sub bletch {
    print "In bletch\n";
    my $not_so_defined;
    $not_so_defined->barf();
    print "Unlikely to be printed\n";

}

以下是运行foo.pl时打印的内容:

In foo
In bar
In bletch
Trace begun at foo.pl line 17
main::__ANON__('Can\'t call method "barf" on an undefined value at ./foo.pl line 32.^J') called at /vcm/home/apps/perl-5.12.1/lib/site_perl/5.12.1/Try/Tiny.pm line 100
Try::Tiny::try('CODE(0xf503a0)', 'Try::Tiny::Catch=REF(0x1035ca0)') called at foo.pl line 19
main::foo at foo.pl line 9

2 个答案:

答案 0 :(得分:4)

对我来说,看起来似乎没有。至少,不要在调用堆栈中更深层次地创建堆栈帧,比如在错误点,或者使用较少的hamfisty try / catch实现。

Try :: Tiny只是eval的一个非常薄的包装器。这意味着,它基本上会侵犯try子,然后在catch真实的情况下运行$@子。到catch子运行时,try“块”已经已经返回,堆栈帧消失了。没有优化 - 只是消失了eval的返回已经杀死了堆栈帧,因为它正在评估它。你真正留下的只是$@中的错误信息。

答案 1 :(得分:3)

  

以下是一个简单的例子。正如您将看到的,堆栈跟踪中既不包含bar()也不包含bletch()。

是的,因为在获得堆栈跟踪之前,您已退出barbletch

创建$SIG{__DIE__}处理程序。