Remember Your Responsibilities
A colleague encountered an odd problem with some Perl code the other day. It took us a while to realise what was going on, you'll probably work it out much quicker ...
Here's a simplified version of what we were dealing with:
use strict;
use warnings;
eval {
my $obj = SomeClass->new();
die "Code Red!\n";
};
if($@) {
print "Exception caught: $@\n";
}
else {
print "No exception occurred\n"
}
We both expected it to output:
Exception caught: Code Red!
but instead we got:
No exception occurred
You probably worked it out straightaway but for the record, here's what was happening ...
The die statement did generate an exception and the message was stored in $@. Of course the code in the eval block stopped executing immediately but when control flow exited the block, any lexcial variables declared in the block went out of scope. In this case there was only one: $obj. What we didn't realise is that $obj's class defined a destructor method ('DESTROY'). This method is called when the object goes out of scope and apparently in our case the method
wrapped something in an eval. Whatever that something was, it completed without generating an exception, so $@ ended up empty - indicating no error and overwriting the exception message that our code put there..
So, if you write a destructor method and it needs to use eval, please remember to use local($@) to restore the previous value of $@ when your routine completes.
Comments