3

eval()最近我在几个地方遇到了这个函数(一些 D 和 JavaScript 代码)。这段经历让我意识到我不明白有或没有语言之间的区别eval()

事实上,我已经能够在不使用它的情况下生存(虽然有时很诱人:))。

您是否知道实现语言和不实现它的语言之间的任何根本区别eval()(即使它是在编译时)?如果没有根本差异,是否存在表现力差异?

您是否知道任何论文或参考资料来解释由 提供的附加计算能力/表现力是eval()什么?eval()也就是说,如果没有它(或以更高的成本),我们可以用什么来实现?

4

1 回答 1

4

有语言和没有语言的能力没有区别eval。你总是可以eval用一种没有它的语言来实现自己,尽管它在某些语言(Lisp)中更容易,而在其他语言(C)中更难。这就是为什么我们知道它不会为语言添加任何新功能。

Eval 通常被认为是“强大但危险且在生产代码中不必要的”。如果您曾经审查过您的源代码,并且它使用了eval.,那么您将不得不习惯人们告诉您不要使用eval. 通常,如果您使用eval,有一种更直接、更安全的方式来完成相同的任务。

安全漏洞

eval功能通常会导致安全漏洞,例如在 Web 应用程序中。例如,在 Python 中:

i = input('Enter a number> ')

Python 3.x 之前的input函数评估用户输入,导致安全问题:

输入一个数字> __import__('os').system('rm -rf $HOME') # 不要尝试这个

这可以在完全沙盒化的运行时中避免,例如 JavaScript、Lua、CLI 等。但是,在没有沙盒化的代码中,安全使用太难了eval

REPL

一个光荣的用途eval是 REPL,它是软件开发的有用工具。在 Google Chrome 中,您现在可以通过按下来Ctrl+Shift+I启动 REPL——只需在出现的框中输入 JavaScript 即可。Firefox 和 Safari 也都有 REPL。

为什么不包括eval

eval功能通常非常复杂。将其包含在标准库中意味着库或运行时必须包含该语言的完整编译器或解释器,这是一大块代码。这就是为什么您通常会eval在通常解释或 JITed 的语言中看到的原因——Lisp、Python 和 JavaScript 运行时通常已经包含一个完整的编译器,所以eval没有额外的包袱。

for C 的实现eval是真正的野兽,因此它们是可选的并被塞入库中。

于 2012-11-10T10:03:57.887 回答