2012-07-24 15 views
23

Non sto sostenendo che questo avrebbe mai una buona idea, ma ho scoperto che si può mandare in crash Python (2.7 e 3.2 controllato) eseguendo eval su un grande stringa di input abbastanza:Perché c'è un limite di lunghezza all'eval di Python?

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

On il mio computer S può essere generato bene, ma per valori di circa N>74900, Python fallirà con Segmentation fault (core dumped). Esiste un limite alla lunghezza della stringa (o dell'albero di analisi) che l'interprete può gestire?

Nota: Non ho bisogno per fare questo, per me questa è una domanda più profonda che riflette la mia ignoranza di ciò che accade all'interno della scatola. Mi piacerebbe capire perché Python fallisce qui, e in modo così catastrofico (perché non lanciare un'eccezione?)

+7

IIRC, l'interprete Python segfaulting è considerato un bug in qualsiasi situazione, e non dovrebbe accadere - questo potrebbe valere un [bug report] (http://bugs.python.org/). –

+4

@Lattyware: nella maggior parte delle situazioni, non tutte. Ma questo * dovrebbe * essere considerato un bug. –

+0

Interessante, 'sum (xrange (75000))' sembra funzionare bene – inspectorG4dget

risposta

18

Questo problema è causato da uno stack overflow nel compilatore CPython. Un modo semplice per riprodurre lo stesso problema è

>>> code = compile("1" + "+1" * 1000000, "", "eval") 
Segmentation fault 

che dimostra che il segfault sta accadendo in fase di compilazione, non durante la valutazione. (Naturalmente questo è anche facile da confermare con gdb.)

[Nota a margine: per le espressioni più piccole, il compilatore applica comunque il piegamento costante qui, quindi l'unica cosa che accade durante l'esecuzione del codice è caricare il risultato :.

>>> code = compile("1" + "+1" * 1000, "", "eval") 
>>> eval(code) 
1001 
>>> dis.dis(code) 
    1   0 LOAD_CONST   1000 (1001) 
       3 RETURN_VALUE   

Fine della nota a margine]

Questo problema è un known defect. Gli sviluppatori Python hanno raccolto diversi modi per bloccare l'interprete Python nello directory Lib/test/crashers della distribuzione di origine. Quello corrispondente a questo problema è Lib/test/crashers/compiler_recursion.py.

+0

Solo per il riferimento, questo sembra essere risolto in Python 3.3+. Il codice genera "RecursionError: profondità massima di ricorsione superata durante la compilazione" ora. –

Problemi correlati