Why do I need to localize $@ before using eval?

I am aware that $@ is a global variable, but I cannot understand why I need to localize it before using eval :

For instance:

 eval { SOME_FUNC_THAT_MAY_DIE(); }; if ( $@ ) { print "An error occured!\n"; } 

The only possible thing I can think of is that if any signal handler calls die at the same time, I will try to read $@ , what am I missing here?

+6
source share
2 answers

The reason for saying local $@ before calling eval is to refuse to go to your caller $@ . It’s rude for a subprogram to modify any global variables (if only one of the declared goals of the subprogram). This is not a problem with top-level code (not inside any subroutine).

In addition, on older Perl, any eval that is called during the destruction of an object will be clobber global $@ (if the object was destroyed because an exception was thrown from the eval block) if $@ not localized first. This was fixed in 5.14.0 , but many people still use old Perls.

+12
source

The documentation of the Try :: Tiny module provides the rationale (and also provides an alternative):

When you run the eval block and it succeeds, $@ will be cleared, which potentially kills the error that is being caught. This triggers an action from a distance, eliminating previous errors that your caller has not yet processed. $ @ must be properly localized before calling eval to avoid this problem. More specifically, $@ gets off at the beginning of eval, which also makes it impossible to capture the previous error before you die (for example, when creating exception objects with error stacks).
+9
source

Source: https://habr.com/ru/post/919699/


All Articles