Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm aware of the fact that $@ is a global variable, still I can't figure out 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, if some signal handler will call die at the same time I try to read $@, what am I missing here?

like image 451
snoofkin Avatar asked Jul 04 '12 19:07

snoofkin


People also ask

What does Eval () do in JavaScript?

eval () is a function property of the global object. The argument of the eval () function is a string. If the string represents an expression, eval () evaluates the expression. If the argument represents one or more JavaScript statements, eval () evaluates the statements.

Does the eval () function work in the local or global scope?

If you use the eval function indirectly, by invoking it via a reference other than eval, as of ECMAScript 5 it works in the global scope rather than the local scope.

Why should I never use Eval ()?

Never use eval ()! eval () is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval () with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension.

How do I use %Eval in SAS?

SAS %eval() Function - Evaluate Expressions in SAS Macro When working in the SAS Macro Language, you can use the %eval() function to evaluate logical expressions and perform integer arithmetic. Skip to primary navigation Skip to main content


2 Answers

The reason to say local $@ before calling eval is to avoid stepping on your caller's $@. It's rude for a subroutine to alter any global variables (unless that's one of the stated purposes of the subroutine). This isn't really an issue with top-level code (not inside any subroutine).

Also, on older Perl's, any eval called during object destruction would clobber the global $@ (if the object was being destroyed because an exception was being thrown from an eval block) unless $@ was localized first. This was fixed in 5.14.0, but many people are still running older Perls.

like image 196
cjm Avatar answered Nov 15 '22 07:11

cjm


The Try::Tiny module documentation gives the rationale (as well as providing an alternative):

When you run an eval block and it succeeds, $@ will be cleared, potentially clobbering an error that is currently being caught. This causes action at a distance, clearing previous errors your caller may have not yet handled. $@ must be properly localized before invoking eval in order to avoid this issue. More specifically, $@ is clobbered at the beginning of the eval, which also makes it impossible to capture the previous error before you die (for instance when making exception objects with error stacks).
like image 23
JRFerguson Avatar answered Nov 15 '22 08:11

JRFerguson