Những cạm bẫy phổ biến được kết hợp với số eval
của Perl, điều gì có thể khiến bạn chọn sử dụng mô-đun như Try::Tiny
?Những cạm bẫy phổ biến khi sử dụng eval của Perl là gì?
Trả lời
Perl của eval
đến trong hai mùi vị, chuỗi eval và khối eval. String eval gọi trình biên dịch để thực thi mã nguồn. Block eval bao quanh mã đã được biên dịch trong trình bao bọc sẽ bắt ngoại lệ die
. (chuỗi eval cũng bắt được ngoại lệ die
cũng như bất kỳ lỗi biên dịch nào).
Thử :: Tiny chỉ áp dụng cho dạng khối của eval, nhưng những điều sau áp dụng cho cả hai biểu mẫu.
Mỗi lần bạn gọi eval
, nó sẽ thay đổi giá trị [email protected]
. Nó sẽ là ''
nếu eval đã thành công hoặc lỗi do eval đánh bắt.
Điều này có nghĩa là bất kỳ khi nào bạn gọi eval, bạn sẽ xóa mọi thông báo lỗi trước đó. Try::Tiny
bản địa hóa biến số [email protected]
cho bạn, sao cho một eval thành công sẽ không xóa thông điệp của lần đánh bại trước đó thất bại.
Sự cố khác xuất phát từ việc sử dụng [email protected]
làm séc để xác định xem eval có thành công hay không. Một mô hình phổ biến là:
eval {...};
if ([email protected]) {
# deal with error here
}
này dựa trên hai giả định, đầu tiên mà bất kỳ thông báo lỗi [email protected]
có thể chứa là một giá trị đúng (thường là true), và rằng không có mã giữa khối eval và tuyên bố nếu.
Tất nhiên, điều này là đúng, nhưng nếu khối eval tạo một đối tượng và đối tượng đó không nằm trong phạm vi sau khi eval thất bại, thì phương thức DESTROY
của đối tượng sẽ được gọi trước câu lệnh if
. Nếu DESTROY
xảy ra để gọi eval mà không cần bản địa hóa [email protected]
và thành công, thì vào thời điểm phát biểu if
của bạn, biến số [email protected]
sẽ bị xóa.
Các giải pháp cho những vấn đề này là:
my $return = do {
local [email protected];
my $ret;
eval {$ret = this_could_fail(); 1} or die "eval failed: [email protected]";
$ret
};
phá vỡ dòng cách nhau một dòng, local [email protected]
tạo ra một mới [email protected]
cho do
khối mà ngăn chặn clobbering giá trị trước đó. my $ret
sẽ là giá trị trả về của mã được đánh giá. Trong khối eval, $ret
được gán cho, và sau đó khối trả về 1
. Bằng cách đó, không có vấn đề gì, nếu eval thành công nó sẽ trả về true, và nếu nó không thành công nó sẽ trả về false. Đó là vào bạn những gì phải làm trong trường hợp thất bại. Đoạn mã trên chỉ chết, nhưng bạn có thể dễ dàng sử dụng giá trị trả về của khối eval để quyết định chạy mã khác.
Vì câu chú giải ở trên hơi tẻ nhạt, nó trở nên dễ bị lỗi.Sử dụng mô-đun như Try::Tiny
cách ly bạn khỏi những lỗi tiềm ẩn đó, với chi phí của một vài cuộc gọi hàm trên mỗi eval. Điều quan trọng là phải biết cách sử dụng eval đúng cách, bởi vì Try::Tiny
sẽ không giúp bạn nếu bạn phải sử dụng chuỗi eval.
Cố định trong bản phát hành hiện tại. – tchrist
Chỉnh sửa nhỏ - '$ @' sẽ thực sự là một chuỗi rỗng thay vì undef nếu không có ngoại lệ nào được ném. –
@Grant McLean => cảm ơn, tôi đáng lẽ phải nhớ, vì đó là cách giao dịch repl thông thường của tôi với lỗi: 'perl -wE 'nói eval, $ @ trong khi <>'' –
Các sự cố được giải thích trong Try::Tiny documentation. Tóm lại, đó là:
Ngoài các câu trả lời ở trên, tôi sẽ thêm ...
- eval bị ảnh hưởng bởi
$SIG{__DIE__}
xử lý gây ra hành động toàn cầu ở một khoảng cách. - Thật dễ dàng cho một người mới gây nhầm lẫn
eval BLOCK
vàeval STRING
, vì chúng dường như làm điều tương tự, nhưng một là một lỗ hổng bảo mật.
Hãy thử :: Tiny có những cạm bẫy riêng của mình, lớn nhất là trong khi nó trông giống như một khối nó thực sự là một cuộc gọi chương trình con. Điều đó có nghĩa này:
eval {
...blah blah...
return $foo;
};
và điều này:
try {
...blah blah...
return $foo;
};
không làm điều tương tự. Chúng được trình bày trong số CAVEATS section of the Try::Tiny docs. Điều đó nói rằng, tôi muốn giới thiệu nó trên eval
.
Bạn đang nói rằng 'eval' là * vẫn * bất ngờ bị phá vỡ trong 5,14? ** Thật sao? ** Đó sẽ là * cực kỳ * đáng thất vọng, bởi vì tôi biết rất nhiều công việc đã đi vào nó để cố gắng làm cho 'Try :: Tiny' lỗi thời bằng cách sửa chữa bất cứ lỗi nào nằm bên dưới' eval'.Nếu nỗ lực đó thất bại, thì có một vấn đề khủng khiếp vì 'Try :: Tiny' vẫn chỉ là một mô-đun CPAN, không phải là cốt lõi. Nếu bạn không thể làm công việc thực sự, và đáng tin cậy, với cốt lõi, thì đó là một tình huống không thể chấp nhận được. – tchrist
@tchrist Quên về điều đó. Như tôi đã hiểu, 5.14.0 đã sửa một lớp lỗi liên quan đến việc phá hủy đối tượng giữa $ @ và đối tượng và thường được tạo thành 'eval {...}; nếu ($ @) {...} 'đáng tin cậy hơn. Tôi tin rằng giải quyết 2 trong 3 điều Hãy thử :: Sửa lỗi nhỏ ... và thứ ba (sai $ @) là khá khó xảy ra. Nó vẫn để lại những điểm tôi đã đề cập. Nó sẽ là một tính năng 5.16 tốt đẹp để ngăn chặn '$ SIG {__ DIE __}' khỏi bắn bên trong một eval. Và quay xuống phim, anh chàng. – Schwern
Gọi 'eval STRING' là“ vấn đề an ninh ”không chỉ là quá kịch tính; nó thậm chí không đúng. Tôi đã sử dụng 'eval STRING' vì nó xuất hiện lần đầu tiên trong perl2 khoảng hai mươi ba năm trước, tôi có thể đảm bảo với bạn rằng không bao giờ tôi gặp phải bất kỳ cái gọi là“ vấn đề an ninh ”nào với nó. Chắc chắn, lập trình câm có thể làm những điều ngu ngốc với nó, nhưng điều này là đúng của gần như bất cứ điều gì. Nếu bạn tồn tại trong một thế giới hoang tưởng về bệnh lý, bạn nên sử dụng chế độ taint và/hoặc ngăn an toàn. Trong một thế giới bình thường, 'eval STRING' nhận được rất nhiều công việc hữu ích được thực hiện; xem chương trình * đổi tên * cổ điển. – tchrist
Sử dụng hàm eval trên hàm X11 có thể vẫn không hoạt động.
Mã này được như
eval {
@win_arrays = GetWindowsFromPid($pid);
};
Các kịch bản sẽ được thoát khỏi Lỗi
X đề nghị thất bại: ...
- 1. Những cạm bẫy phổ biến của đồng bộ hóa dựa trên dấu thời gian là gì?
- 2. Cạm bẫy của việc sử dụng sql_variant là gì?
- 3. Những cạm bẫy khi sử dụng FlexibleContexts và FlexibleInstances là gì?
- 4. Cạm bẫy của ADL là gì?
- 5. Những cạm bẫy khi thiết lập enable_nestloop là OFF
- 6. Angular JS: những vấn đề/cạm bẫy của việc sử dụng Angular là gì?
- 7. Một số cạm bẫy Java phổ biến/gotchas cho lập trình C++ là gì?
- 8. Sử dụng cookie cho trạng thái phiên web - những cạm bẫy là gì?
- 9. Những cạm bẫy có thể xảy ra khi chuyển Psyco sang 64-bit là gì?
- 10. Những cạm bẫy của kết nối được nhúng vào Derby qua mạng là gì?
- 11. Những cạm bẫy và gotchas của trộn Objective-C và C là gì?
- 12. Cạm bẫy của các ứng dụng Android
- 13. SharePoint 2007 - RunWithElevatedPrivileges - Cạm bẫy khi sử dụng này
- 14. auto_ptr Bẫy và Cạm bẫy
- 15. Các luồng hoạt động như thế nào trong Python, và những cạm bẫy cụ thể của Python là gì?
- 16. Những cạm bẫy tiềm năng trong việc sử dụng hàng đợi JMS?
- 17. Cạm bẫy của thử nghiệm sau khi phát triển là gì?
- 18. Những cạm bẫy cố gắng sử dụng PLINQ trên các máy phát điện chạy dài?
- 19. Bất kỳ cạm bẫy nào khi sử dụng các công thức được lập trình sẵn?
- 20. Cạm bẫy hiệu suất hibernate thông thường
- 21. Một số trường hợp sử dụng phổ biến để sử dụng Microkernel của Akka là gì?
- 22. Phổ biến UDP là gì?
- 23. Mẫu thiết kế Singleton: Cạm bẫy
- 24. Những sai lầm phổ biến cần tránh khi mã hóa javascript cho Internet Explorer là gì?
- 25. Những cạm bẫy của việc thực thi jQuery mà không có $ (tài liệu) .ready() ;?
- 26. cạm bẫy svn -> git migration
- 27. Cạm bẫy miền-thiết kế (DDD)
- 28. Các cạm bẫy hiệu suất của Apache Velocity?
- 29. Biến $ * của Perl được sử dụng để làm gì?
- 30. Lỗ hổng Java phổ biến là gì?
thể trùng lặp của [Tại sao '$ @ 'không đáng tin cậy?] (http://stackoverflow.com/questions/3686857/why-is-untrustworthy), [Có gì bị hỏng về ngoại lệ trong Perl?] (http://stackoverflow.com/questions/2165161/) – mob
Chỉ lại ason bạn sẽ không sử dụng nội trang là bạn không chạy phiên bản hiện tại của Perl. – tchrist
@mob - vâng, có vẻ như đó là cùng một câu hỏi. – Hugh