2012-07-24 61 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