2012-07-04 26 views
6

Tôi nhận thức được thực tế là [email protected] là một biến toàn cầu, tôi vẫn không thể hiểu tại sao tôi cần phải địa phương hóa nó trước khi sử dụng eval:

Ví dụ:

eval { SOME_FUNC_THAT_MAY_DIE(); }; 
if ([email protected]) { 
    print "An error occured!\n"; 
} 

duy nhất có thể điều tôi có thể nghĩ là, nếu một số xử lý tín hiệu sẽ gọi die cùng một lúc tôi cố gắng để đọc [email protected], những gì tôi thiếu ở đây?

Trả lời

12

Lý do để nói local [email protected] trước khi gọi eval là để tránh giẫm lên người gọi của bạn của [email protected]. Thật là thô lỗ đối với một chương trình con để thay đổi bất kỳ biến toàn cầu nào (trừ khi đó là một trong những mục đích đã nêu của chương trình con). Đây không thực sự là vấn đề với mã cấp cao nhất (không phải bên trong bất kỳ chương trình con nào).

Ngoài ra, trên của Perl cũ, bất kỳ eval gọi trong sự tàn phá đối tượng sẽ clobber toàn cầu [email protected] (nếu đối tượng đã bị phá hủy vì một ngoại lệ đã được ném từ một khối eval) trừ khi [email protected] được địa phương đầu tiên. Đây là fixed in 5.14.0, nhưng nhiều người vẫn đang chạy Perls cũ hơn.

9

Các tài liệu Try::Tiny mô-đun cung cấp cho các lý do (cũng như cung cấp một thay thế):

Khi bạn chạy một khối eval và nó thành công, $ @ sẽ bị xóa, có khả năng clobbering một lỗi mà hiện đang được bắt. Điều này gây ra hành động ở khoảng cách, xóa các lỗi trước đó mà người gọi của bạn có thể chưa xử lý. $ @ phải được bản địa hóa chính xác trước khi gọi eval để tránh sự cố này. Cụ thể hơn, $ @ bị ghi đè ở đầu eval, điều này cũng khiến bạn không thể chụp được lỗi trước đó trước khi chết (ví dụ khi tạo các đối tượng ngoại lệ có lỗi ngăn xếp).
+0

Lý do tôi tìm thấy bài đăng này, chính xác là vì tôi không hiểu chính xác đoạn này trong tài liệu Try :: Tiny. Lỗi 'có khả năng che giấu một lỗi hiện đang bị bắt' nghĩa là gì? ;-) –