1

我滚动浏览 Test::More 的代码,因为我想看看是如何实现的(use_ok以及require_ok为什么 Ovid 不喜欢它们)。我来到了_eval子例程,其中包含一些我不完全理解的特殊逻辑,用于在eval调用期间保护变量。我从Try::Tiny的文档中了解到处理$@. 但是,我不明白和的处理$!$SIG{__DIE__}下面逐字复制块):

# Work around oddities surrounding resetting of $@ by immediately
# storing it.
my( $sigdie, $eval_result, $eval_error );
{
    local( $@, $!, $SIG{__DIE__} );    # isolate eval
    $eval_result = eval $code;              ## no critic (BuiltinFunctions::ProhibitStringyEval)
    $eval_error  = $@;
    $sigdie      = $SIG{__DIE__} || undef;
}
# make sure that $code got a chance to set $SIG{__DIE__}
$SIG{__DIE__} = $sigdie if defined $sigdie;

的处理$SIG{__DIE__}RT #34065有关,但我仍然不明白。为什么有必要在最后一行再次设置变量,因为它应该总是在块的最后一行设置?如果这些行的全部目的是将变量设置为eval调用中的任何内容,那么为什么必须首先将其本地化?

另外,如果使用eval不破坏错误变量意味着本地化$@and $!,我们是否也不必本地化$?

4

1 回答 1

2

在我看来,$sigdie是否有明确允许 eval 的代码设置 $SIG{__DIE__},同时不允许任何外部设置的处理程序在 eval 期间生效。

因此本地化抑制了外部值,但需要在块结束之前保存任何设置值,并在块之后将其设置为现在未本地化的版本。

出于实际原因,我假设$!是本地化的,但不是$?,$^E等(也就是说,我猜人们抱怨$!改变,但没有别的)。

于 2014-01-07T23:16:05.403 回答