Perl FAQ 4.16: What is variable suicide and how can I prevent it?

Perl FAQ 4.16

What is variable suicide and how can I prevent it?

Variable suicide is a nasty side effect of dynamic scoping and the way variables are passed by reference. If you say

    $x = 17;
    &munge($x);
    sub munge {
	local($x);
	local($myvar) = $_[0];
	...
    } 

Then you have just clobbered $_[0]! Why this is occurring is pretty heavy wizardry: the reference to $x stored in $_[0] was temporarily occluded by the previous local($x) statement (which, you're recall, occurs at run-time, not compile-time). The work around is simple, however: declare your formal parameters first:

    sub munge {
	local($myvar) = $_[0];
	local($x);
	...
    }
    

That doesn't help you if you're going to be trying to access @_ directly after the local()s. In this case, careful use of the package facility is your only recourse.

Another manifestation of this problem occurs due to the magical nature of the index variable in a foreach() loop.

    @num = 0 .. 4;
    print "num begin  @num\n";
    foreach $m (@num) { &ug }
    print "num finish @num\n";
    sub ug {
	local($m) = 42;
	print "m=$m  $num[0],$num[1],$num[2],$num[3]\n";
    }
    

Which prints out the mysterious:
    num begin  0 1 2 3 4
    m=42  42,1,2,3
    m=42  0,42,2,3
    m=42  0,1,42,3
    m=42  0,1,2,42
    m=42  0,1,2,3
    num finish 0 1 2 3 4

What's happening here is that $m is an alias for each element of @num. Inside &ug, you temporarily change $m. Well, that means that you've also temporarily changed whatever $m is an alias to!! The only workaround is to be careful with global variables, using packages, and/or just be aware of this potential in foreach() loops.

The perl5 static autos via my() do not exhibit this problem.


Other resources at this site: