与Perl的eval
相关的常见问题有哪些,这可能会使您选择使用诸如Try::Tiny
之类的模块?使用Perl的eval时常见的缺陷是什么?
回答
Perl的eval
有两种版本,字符串以及eval块EVAL。字符串eval调用编译器来执行源代码。 Block eval包围了已包装在代码中的代码,该代码将捕获die
异常。 (字符串eval还捕获die
异常,以及任何编译错误)。
Try :: Tiny仅适用于eval的块形式,但以下内容适用于这两种形式。
每当您拨打eval
时,它将更改[email protected]
的值。如果eval成功或者由eval捕获到错误,它将是''
。
这意味着,只要您调用eval,您将清除以前的任何错误消息。 Try::Tiny
为您定制了[email protected]
变量,以便成功的eval不会清除之前失败的eval的消息。
另一个缺陷来自于使用[email protected]
作为检查以确定eval是否成功。一个常见的模式是:
eval {...};
if ([email protected]) {
# deal with error here
}
这依赖于两个假设,第一,任何错误信息[email protected]
可以包含是一个真值(通常为真),并且存在的eval块和if语句之间没有任何代码。
当然,当然后者是真的,但是如果eval块创建了一个对象,并且该对象在eval失败后超出范围,那么将在if
语句之前调用该对象的DESTROY
方法。如果DESTROY
恰好在没有本地化[email protected]
的情况下调用eval并且成功,那么在您的if
语句运行时,[email protected]
变量将被清除。
的解决这些问题的是:
my $return = do {
local [email protected];
my $ret;
eval {$ret = this_could_fail(); 1} or die "eval failed: [email protected]";
$ret
};
打破了由线,除了线,所述local [email protected]
为do
块这防止重挫先前值创建一个新的[email protected]
。 my $ret
将作为评估代码的返回值。在eval块中,$ret
被分配给,然后该块返回1
。这样,无论如何,如果eval成功,它将返回true,如果失败,它将返回false。在失败的情况下,你应该怎么做。上面的代码只是死掉了,但你可以很容易地使用eval块的返回值来决定运行其他代码。
由于上面的咒语有点乏味,因此容易出错。使用像Try::Tiny
这样的模块可以避免潜在错误,但需要花费几个函数调用每个eval。知道如何正确使用eval非常重要,因为如果您必须使用字符串eval,Try::Tiny
不会帮助您。
已在当前版本中修复。 – tchrist
小修正 - 如果没有抛出异常,'$ @'实际上是一个空字符串而不是undef。 –
@Grant McLean =>谢谢,我应该记住,因为这就是我平常的repl处理错误的方式:'perl -wE'说eval,$ @ while <>'' –
这些问题在Try::Tiny documentation中有解释。简单地说,他们是:
除了上述问题的答案,我想补充...
- EVAL通过在距离全球
$SIG{__DIE__}
处理造成动作的影响。 - 新手很容易混淆
eval BLOCK
和eval STRING
,因为它们似乎做同样的事情,但一个是安全漏洞。
Try :: Tiny有它自己的陷阱,最大的问题是虽然它看起来像一个块,但它实际上是一个子程序调用。这意味着这样的:
eval {
...blah blah...
return $foo;
};
这:
try {
...blah blah...
return $foo;
};
不会做同样的事情。这些都在CAVEATS section of the Try::Tiny docs中列出。这就是说,我会推荐它通过eval
。
你是说'eval' *仍然*无法在5.14中破解? **真的吗?**这会令人非常失望,因为我知道很多工作都是为了试图通过修复困扰eval的任何潜在错误来渲染'Try :: Tiny'。如果这种努力失败了,那么存在一个可怕的问题,因为'Try :: Tiny'仍然只是一个CPAN模块,而不是核心。如果你无法做到真正的工作,并且可靠地完成核心工作,那么这是一个不可接受的情况。 – tchrist
@tchrist忘记了这一点。据我了解,5.14.0修复了一类与$ @和对象销毁之间的交互有关的bug,并且通常会产生'eval {...};如果($ @){...}'更可靠。我相信解决了Try :: Tiny 3个问题中的2个问题......而第三个问题(假的$ @)是不太可能的。它仍然留下我提到的观点。在eval内部放置'$ SIG {__ DIE __}'是一个不错的特性。并拨打电视剧,哥们。 – Schwern
调用'eval STRING'是一个“安全问题”不仅过于戏剧化;它甚至不是真的。自从23年前它首次出现在perl2以来,我使用了'eval STRING',我可以向你保证,我从来没有遇到过任何所谓的“安全问题”。当然,愚蠢的程序员可以用它做一些愚蠢的事情,但几乎任何事情都是如此。如果你存在于一个病态偏执的世界,你应该使用污染模式和/或安全隔间。在一个普通的世界里,'eval STRING'完成了很多有用的工作;请参阅经典*重命名*程序。 – tchrist
对X11函数使用eval可能仍然无法保持活动状态。
代码如下
eval {
@win_arrays = GetWindowsFromPid($pid);
};
的脚本将被从失败的请求
X错误退出:...
- 1. 构建时区感知应用程序时,常见的缺陷(以及要测试的东西)是什么?
- 2. 使用方向时,“缺少文件名”的Eclipse缺陷是什么?
- 3. 使用SVGZ而不是SVG的缺陷是什么?
- 4. 使用perl cgi时发生错误500 - 但不是任何常见陷阱
- 5. 什么是常见的开发问题,陷阱和建议?
- 6. 什么是网站跟踪软件缺陷/缺陷?
- 7. 使用sql_variant有什么缺陷?
- 8. 使用盒子尺寸的缺陷是什么:边框?
- 9. 什么是使UnityContainer不是线程安全的缺陷?
- 10. 缺陷率跟踪最适合什么?每个KLOC的缺陷?
- 11. 看不见的缺陷,应用stucks
- 12. UITableViewRowAnimation具有可见缺陷
- 13. 使用jsp文件时,eclipse中的常见技巧是什么?
- 14. 使用Hibernate时OutOfMemory错误的最常见原因是什么?
- 15. Perl Tk模块的缺点是什么?
- 16. 在安全性方面避免在jsp应用程序中常见的缺陷是什么?
- 17. Perl中多行注释的常见解决方法是什么?
- 18. git fetch的常见用例是什么?
- 19. GTK#常见陷阱
- 20. 为什么Perl的EVAL得到错误
- 21. 你什么时候使用“require-dev”?常见的开发依赖是什么?
- 22. 简单多线程程序的常见缺陷
- 23. perl eval使用包
- 24. 什么数字是最常见的?
- 25. 什么是死锁的常见原因?
- 26. 什么是Apache的常见配置
- 27. 什么是最常见的CSS问题?
- 28. 什么是最常见的CSS实践?
- 29. 什么是最常见的EMACS命令?
- 30. 什么使用,而不是eval在jquery
的[为什么'$可能重复@ '不可信?](http://stackoverflow.com/questions/3686857/why-is-untrustworthy),[Perl中有什么坏例外](http://stackoverflow.com/questions/2165161/) – mob
唯一回覆ason你不会使用内建的是你没有运行当前版本的Perl。 – tchrist
@mob - 是的,这似乎是同一个问题。 – Hugh