我滚动浏览 Test::More 的代码,因为我想看看 use_ok
和 require_ok
已实现(以及为什么 Ovid 不喜欢它们)。我来到了 _eval
子程序,其中包含一些我不完全理解的特殊逻辑,用于在 eval
期间保护变量称呼。我从 Try::Tiny 的文档中了解到处理有多么困难$@
.但是,我不明白 $!
的处理方式和 $SIG{__DIE__}
(以下 block 逐字复制):
# 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 相关,但我还是不明白。为什么有必要在最后一行再次设置变量,因为它应该总是在 block 的最后一行设置?如果这些行的全部目的是将变量设置为 eval
中的任何内容调用,为什么必须首先本地化?此外,如果使用
eval
没有破坏错误变量意味着本地化 $@
和 $!
,我们是否也必须本地化 $?
?
最佳答案
在我看来它像 $sigdie
是否有明确允许评估代码设置$SIG{__DIE__}
,同时不允许任何外部设置的处理程序在评估期间生效。
因此本地化抑制了外部值,但需要在 block 结束之前保存任何设置值,并在 block 之后将其设置为现在未本地化的版本。
我假设 $!
已本地化但不是 $?
, $^E
等出于实际原因(也就是说,我猜人们提示 $!
更改,但没有其他任何东西)。
关于perl - 在 Test::More 中的 eval 期间保护全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20981861/