为什么在使用eval之前我需要本地化$ @?

sno*_*kin 6 perl eval exception die

我知道这$@是一个全局变量的事实,我仍然无法弄清楚为什么我需要在使用eval之前对其进行本地化:

例如:

eval { SOME_FUNC_THAT_MAY_DIE(); };
if ($@) {
  print "An error occured!\n";
}
Run Code Online (Sandbox Code Playgroud)

我能想到的唯一可能的事情是,如果某个信号处理程序会die在我尝试阅读的同时调用,$@我在这里缺少什么?

cjm*_*cjm 12

local $@在打电话之前说的原因eval是为了避免踩到你的来电者$@.子程序改变任何全局变量是非常粗鲁的(除非这是子程序的既定目的之一).对于顶级代码(不在任何子例程中),这实际上不是问题.

此外,在较旧的Perl上,eval在对象破坏期间调用的任何内容都会破坏全局$@(如果对象因为从eval块中抛出异常而被销毁),除非$@首先进行本地化.这在5.14.0中已得到修复,但许多人仍在运行较旧的Perls.


JRF*_*son 9

尝试::微型模块文档给出的理由(以及提供一种替代):

当你运行一个eval块并且它成功时,$ @将被清除,可能会破坏当前被捕获的错误.这会导致远程操作,清除调用者可能尚未处理的先前错误.在调用eval之前,$ @必须正确本地化,以避免此问题.更具体地说,$ @在eval的开头被破坏了,这也使得在你死之前无法捕获先前的错误(例如在制作具有错误堆栈的异常对象时).