为什么Python的eval函数有长度限制?

23

我并不推荐这么做,但我发现如果在Python中运行eval时输入一个足够大的字符串,就会导致Python崩溃(已测试过2.7和3.2版本):

def kill_python(N):
    S = '+'.join((str(n) for n in xrange(N)))
    return eval(S)

在我的电脑上,生成S没有问题,但是对于大约N>74900的值,Python会崩溃并显示Segmentation fault (core dumped)。解释器能处理的字符串(或解析树)长度是否有限制?

注意:我不需要这样做,对我来说,这是一个更深层次的问题,反映了我对盒子内部发生的事情的无知。我想要理解为什么Python会在这里失败,而且失败得如此惨烈(为什么不抛出异常?)


7
据我所知,在任何情况下,Python解释器崩溃都被认为是一个bug,不应该发生-这可能值得进行错误报告 - Gareth Latty
4
在大多数情况下,而不是所有情况。但这个应该被认为是一个 bug。 - Sven Marnach
有趣的是,sum(xrange(75000)) 看起来运行得很好。 - inspectorG4dget
@SvenMarnach 脑海中浮现出一些例外情况(最明显的是扩展模块导致CPython崩溃),但由于这是核心功能,我认为 - 正如你所说 - 这可能是一个错误。 - Gareth Latty
4
这在这里的回答中也有所提及:https://dev59.com/IlTTa4cB1Zd3GeqPwNq- - jmetz
显示剩余8条评论
1个回答

18
这个问题是由CPython编译器中的堆栈溢出引起的。重现相同问题的简单方法是:
>>> code = compile("1" + "+1" * 1000000, "", "eval")
Segmentation fault

证明了段错误是在编译阶段而不是执行阶段发生的。(当然,用gdb也容易确认。)
[旁注:对于较小的表达式,编译器会在此处应用常量折叠,因此代码执行期间唯一发生的事情就是加载结果:]
>>> code = compile("1" + "+1" * 1000, "", "eval")
>>> eval(code)
1001
>>> dis.dis(code)
  1           0 LOAD_CONST            1000 (1001)
              3 RETURN_VALUE        

附注结束。

这个问题是一个已知缺陷。Python开发人员在源代码分布的目录Lib/test/crashers中收集了几种导致Python解释器崩溃的方法。与此问题相对应的是Lib/test/crashers/compiler_recursion.py


仅供参考,这个问题似乎在Python 3.3+中已经被修复了。现在代码会引发 RecursionError: maximum recursion depth exceeded during compilation 错误。 - Vlad Frolov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接