2012-07-24 59 views
23

tôi không ủng hộ rằng điều này sẽ không bao giờ là một ý tưởng tốt, nhưng tôi đã phát hiện ra rằng bạn có thể sụp đổ Python (2,7 và 3,2 kiểm tra) bằng cách chạy eval trên một chuỗi đầu vào đủ lớn:Tại sao có giới hạn độ dài cho python's eval?

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

On máy tính của tôi S có thể được tạo tốt, nhưng đối với các giá trị khoảng N>74900, Python sẽ không thành công với Segmentation fault (core dumped). Có giới hạn về độ dài của chuỗi (hoặc phân tích cây) mà trình thông dịch có thể xử lý không?

Note: Tôi không cần để làm điều này, với tôi đây là một câu hỏi sâu hơn phản ánh sự thiếu hiểu biết của tôi về những gì diễn ra bên trong hộp. Tôi muốn hiểu lý do tại sao Python không ở đây, và vì vậy thảm khốc (tại sao không ném một ngoại lệ?)

+7

IIRC, việc phân tách thông dịch viên Python được coi là lỗi trong mọi tình huống và không nên xảy ra - điều này có thể đáng giá [báo cáo lỗi] (http://bugs.python.org/). –

+4

@Lattyware: Trong hầu hết các trường hợp, không phải tất cả. Nhưng cái này * nên * được coi là một lỗi. –

+0

Thật thú vị, 'sum (xrange (75000))' dường như chỉ hoạt động tốt – inspectorG4dget

Trả lời

18

Vấn đề này là do tràn ngăn xếp trong trình biên dịch CPython. Một cách dễ dàng để tái tạo cùng một vấn đề là

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

chứng minh rằng sự phân đoạn xảy ra ở giai đoạn biên dịch, chứ không phải trong quá trình đánh giá. (Tất nhiên điều này cũng dễ xác nhận với gdb.)

[Ghi chú bên: Đối với các biểu thức nhỏ hơn, trình biên dịch sẽ áp dụng xếp liên tục ở đây, vì vậy điều duy nhất xảy ra trong khi thực thi mã là tải kết quả :.

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

End của mặt lưu ý]

vấn đề này là một known defect. Các nhà phát triển Python đã thu thập một số cách để phá vỡ trình thông dịch Python trong số directory Lib/test/crashers của bản phân phối nguồn. Số tương ứng với số này là Lib/test/crashers/compiler_recursion.py.

+0

Chỉ để tham khảo, điều này dường như được sửa trong Python 3.3+. Mã tăng 'RecursionError: độ sâu đệ quy tối đa vượt quá trong quá trình biên dịch' ngay bây giờ. –

Các vấn đề liên quan