使用Perl';什么是评估?
与Perl相关联的常见陷阱有哪些,这些陷阱可能会让您选择使用模块,例如?这些问题将在中解释。简而言之,它们是:使用Perl';什么是评估?,perl,exception,eval,Perl,Exception,Eval,与Perl相关联的常见陷阱有哪些,这些陷阱可能会让您选择使用模块,例如?这些问题将在中解释。简而言之,它们是: Perl的eval有两种风格,字符串eval和块eval。String eval调用编译器来执行源代码。Block eval将已编译的代码包围在一个包装器中,该包装器将捕获die异常。(字符串eval还捕获die异常以及任何编译错误) Try::Tiny仅适用于eval的块形式,但以下两种形式都适用 每次调用eval时,它都会更改$@的值。如果评估成功或被评估捕获到错误,则它将
- Perl的
eval
有两种风格,字符串eval和块eval。String eval调用编译器来执行源代码。Block eval将已编译的代码包围在一个包装器中,该包装器将捕获die
异常。(字符串eval还捕获die
异常以及任何编译错误)
Try::Tiny仅适用于eval的块形式,但以下两种形式都适用
每次调用eval
时,它都会更改$@
的值。如果评估成功或被评估捕获到错误,则它将是'
这意味着,无论何时调用eval,都将清除以前的所有错误消息Try::Tiny
为您本地化$@
变量,以便成功的评估不会清除先前失败评估的消息
另一个陷阱是使用$@
作为检查来确定评估是否成功。一种常见的模式是:
eval {...};
if ($@) {
# deal with error here
}
这取决于两个假设,首先,任何错误消息$@
可能包含的值都是真值(通常为真),并且eval块和if语句之间没有代码
从视觉上看,后者当然是正确的,但是如果eval块创建了一个对象,并且该对象在eval失败后超出了范围,那么该对象的DESTROY
方法将在if
语句之前被调用。如果DESTROY
碰巧调用eval而没有本地化$@
,并且调用成功,那么在运行If
语句时,$@
变量将被清除
解决这些问题的办法是:
my $return = do {
local $@;
my $ret;
eval {$ret = this_could_fail(); 1} or die "eval failed: $@";
$ret
};
将该行逐行分解,本地$@会为do
块创建一个新的$@
,以防止对以前的值进行碰撞my$ret
将是计算代码的返回值。在eval块中,$ret
被分配给,然后块返回1
。这样,不管怎样,如果eval成功,它将返回true,如果失败,它将返回false。万一失败,该怎么办由你决定。上面的代码刚刚结束,但是您可以很容易地使用eval块的返回值来决定运行其他代码
因为上面的咒语有点乏味,所以很容易出错。使用像
Try::Tiny
这样的模块可以将您从这些潜在错误中隔离出来,而每次评估的代价是多调用几个函数。知道如何正确使用eval是很重要的,因为如果必须使用字符串eval,Try::Tiny
对您没有帮助。除了上面的答案,我还要补充
- eval受全局
处理程序的影响,该处理程序在一定距离内导致操作$SIG{{uuuuu DIE}
- 新手很容易混淆
和eval BLOCK
,因为它们似乎做了相同的事情,但其中一个是安全漏洞eval STRING
eval {
...blah blah...
return $foo;
};
这是:
try {
...blah blah...
return $foo;
};
不要做同样的事情。这些都在地图上标出了。也就是说,我建议使用eval-on-X11函数,而不要使用eval-on-X11函数 代码如下
eval {
@win_arrays = GetWindowsFromPid($pid);
};
脚本将从中退出
失败请求的X错误:
可能重复,您不使用内置的唯一原因是您没有运行当前版本的Perl。@mob-是的,这似乎是同一个问题。运行5.14或更高版本,告诉我这是否适用于您。@tchrist确实适用。谢谢你指出这一点。我真不敢相信我错过了。这里是供参考的链接:谢谢。虽然我在Try:Tiny上阅读了介绍,但我未能阅读背景部分。在当前版本中已修复。在当前版本中已修复。如果没有引发异常,则Tiny correction-
$@
实际上将是一个空字符串,而不是未定义。@Grant McLean=>谢谢,我应该记得,因为这就是我通常的repl处理错误的方式:perl-我们说eval,$@而“
你是说eval
在5.14中仍然无法使用吗?真正地这将是非常令人失望的,因为我知道它做了很多工作,试图通过修复任何困扰eval
的底层bug,使try::Tiny
过时。如果这一努力失败了,那么就会出现一个可怕的问题,因为Try::Tiny
仍然只是一个CPAN模块,而不是核心。如果你不能用核心做真正的、可靠的工作,那么这是一个不可接受的情况。@tchrist忘记了这一点。据我所知,5.14.0修复了一类与$@和对象销毁之间的交互有关的bug,通常使eval{…};如果($@){…}
更可靠。我相信这可以解决三件事情中的两件:微小的修复。。。第三个(错误的$@)是不太可能的。它仍然保留了我提到的要点。这将是一个很好的5.16特性,可以阻止$SIG{{{uuuuu DIE}在一个eval内开火。然后把话剧往下拨,伙计。把eval STRING
称为“安全问题”不仅仅是太戏剧化了;这甚至不是真的。我使用了eval STRING
,因为它在23年前首次出现在perl2中,我可以向您保证,我从未遇到过任何所谓的“安全问题”。当然,愚蠢的程序员可以用它做愚蠢的事情,但这几乎适用于任何事情。如果你生活在一个病态偏执的世界,你应该使用污染模式和/或安全隔间。在正常情况下,eval STRING
会得到很多u