gpt4 book ai didi

Perl:$SIG{__DIE__}、eval {} 和堆栈跟踪

转载 作者:行者123 更新时间:2023-12-04 00:37:10 25 4
gpt4 key购买 nike

我有一段 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!" }

现在我想更改该代码,使其执行以下操作:
  • 为每个“冒泡”到最外层( sub outer )的异常打印完整的堆栈跟踪。具体来说,堆栈跟踪应该 不是 停在“eval { }”的第一层。
  • 无需更改任何内部级别的实现。

  • 现在,我这样做的方法是安装一个本地化的 __DIE__ outer 内的处理程序子:
    use Devel::StackTrace;

    sub outer {
    local $SIG{__DIE__} = sub {
    my $error = shift;
    my $trace = Devel::StackTrace->new;
    print "Error: $error\n",
    "Stack Trace:\n",
    $trace->as_string;
    };
    middle();
    }

    [ 编辑 : 我犯了一个错误,上面的代码实际上并没有像我想要的那样工作,它实际上绕过了 middle 的异常处理子。所以我想问题真的应该是:我想要的行为是否可能?]

    这完美地工作,唯一的问题是,如果我正确理解文档,它依赖于明确弃用的行为,即 __DIE__ 的事实。即使在“ die ”内部的“ eval { } ”中也会触发处理程序,这实际上不应该。两者 perlvarperlsub声明此行为可能会在 Perl 的 future 版本中删除。

    有没有另一种方法可以在不依赖已弃用行为的情况下实现这一点,或者即使文档另有说明也可以依靠它?

    最佳答案

    依赖文档所说的已弃用的任何内容都是不安全的。该行为可能(并且可能会)在 future 版本中发生变化。依赖已弃用的行为会将您锁定在您今天运行的 Perl 版本中。

    不幸的是,我没有找到符合您标准的解决方法。 “正确”的解决方案是修改内部方法来调用Carp::confess而不是 die并删除自定义 $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:\temp\foo.pl line 11
    main::inner() called at c:\temp\foo.pl line 9
    eval {...} called at c:\temp\foo.pl line 9
    main::middle() called at c:\temp\foo.pl line 7
    main::outer() called at c:\temp\foo.pl line 5

    因为无论如何你都会死,你可能不需要把电话困在 inner() 中。 . (你没有在你的例子中,你的实际代码可能会有所不同。)

    在您的示例中,您尝试通过 $@ 返回数据.你不能那样做。采用
    my $x = eval { inner(@_) };

    反而。 (我假设这只是将代码简化到足以在此处发布的错误。)

    关于Perl:$SIG{__DIE__}、eval {} 和堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/971273/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com