2012-07-24 26 views
23

我不主张,这将永远是一个好主意,但我发现,您可以通过在一个足够大的输入字符串运行eval崩溃的Python(2.7和3.2选中):为什么python的eval有长度限制?

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

IIRC,Python解释器segfaulting在任何情况下都被认为是一个bug,不应该发生 - 这可能值得[bug报告](http://bugs.python.org/)。 – 2012-07-24 16:26:11

+4

@Lattyware:在大多数情况下,不是全部。但是这个*应该被认为是一个错误。 – 2012-07-24 16:27:33

+0

有趣的是,'sum(xrange(75000))'似乎工作得很好 – inspectorG4dget 2012-07-24 16:27:39

回答

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   

端侧注意]

这个问题是一个known defect。 Python开发人员收集了几种方法来破坏源代码发布版的directory Lib/test/crashers中的Python解释器。与此问题相对应的是Lib/test/crashers/compiler_recursion.py

+0

仅供参考,这似乎是在Python 3.3+中修复的。该代码现在提出了'RecursionError:编译期间超出最大递归深度。 – 2017-04-18 15:01:51