2012-07-24 7 views
23

No estoy abogando por que este nunca sería una buena idea, pero he encontrado que puede chocar Python (2,7 y 3,2 marcada) mediante la ejecución de eval en una gran cadena de entrada es suficiente:¿Por qué hay un límite de longitud para la evaluación de Python?

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

En mi computadora S se puede generar muy bien, pero para valores de aproximadamente N>74900, Python fallará con Segmentation fault (core dumped). ¿Existe un límite en la longitud de la cadena (o árbol de análisis sintáctico) que el intérprete puede manejar?

Nota: No necesito hacer esto, para mí esto es una cuestión más profunda que refleja mi ignorancia de lo que sucede dentro de la caja. Me gustaría entender por qué Python falla aquí, y tan catastróficamente (¿por qué no lanzar una excepción?)

+7

IIRC, el intérprete de intérpretes de Python se considera un error en cualquier situación, y no debería ocurrir; podría valer un [informe de error] (http://bugs.python.org/). –

+4

@Lattyware: en la mayoría de las situaciones, no en todas. Pero este * debería * ser considerado un error. –

+0

Curiosamente, 'sum (xrange (75000))' parece funcionar bien – inspectorG4dget

Respuesta

18

Este problema está causado por un desbordamiento de pila en el compilador CPython. Una manera fácil de reproducir el mismo problema es

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

lo que demuestra que la violación de segmento está sucediendo en la etapa de compilación, no durante la evaluación. (Por supuesto, esto también es fácil de confirmar con gdb.)

[Nota: para las expresiones más pequeñas, el compilador aplicaría plegado constante aquí de todos modos, por lo que lo único que ocurre durante la ejecución del código es cargar el resultado :.

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

Fin de la nota]

Este problema es un known defect. Los desarrolladores de Python recopilaron varias formas de bloquear el intérprete de Python en el directory Lib/test/crashers de la distribución fuente. El que corresponde a este problema es Lib/test/crashers/compiler_recursion.py.

+0

Solo como referencia, esto parece corregido en Python 3.3+. El código aumenta 'RecursionError: profundidad de recursión máxima excedida durante la compilación 'ahora. –

Cuestiones relacionadas