This is a perplexing problem that a co-worker of mine has. And I have not been able to work out the cause, either.
The short version is, in a class he has written, which has a DESTROY
destructor/method defined, DESTROY
is not getting called when the object is destroyed. It is not getting called at the point where we would have thought the object goes out of scope. And while we considered that maybe there was a dangling reference to it somewhere, it isn't being called at script exit, either. We've littered the class and the script with debugging print
statements, and even made an explicit call to it in an END
block just to verify that we hadn't somehow put it in the wrong namespace. (We hadn't. The explicit call triggered all the print
statements as expected.)
So I'm puzzled by this, and am just as interested in the answer as he is. What situations might lead to this behavior? The script in question is exiting cleanly - there is no call to POSIX::_exit
or anything like that. The only "variable" in this is that the class is using Class::MethodMaker
to define some accessors and the constructor. However, there are no references in the Class::MethodMaker
docs to having interaction with (or overriding) a class DESTROY
method.
Without seeing the code, one cannot know what is going wrong. But I can imagine a scenario where it would seem like your DESTROY() method is not called:
#!/usr/bin/perl
use strict;
use warnings;
sub DESTROY {
die {};
print "DESTROY\n";
}
{
print "creating object...\n";
my $obj = bless {};
print "it goes out of scope...\n";
}
print "object is out of scope\n";
This script prints:
creating object...
it goes out of scope...
object is out of scope
Probably, the error is not as obvious as in this example. The die() call could be deep in the DESTROY code.
The die() call may be caused by some condition that you did not think of. Objects are undef'ed in arbitrary order during global destruction:
#!/usr/bin/perl
use strict;
use warnings;
sub DESTROY {
die {} if ! defined $_[0]->[0];
print "$_[0]->DESTROY()\n";
}
print "creating objects...\n";
my $x = bless [];
my $y = bless [$x];
$x->[0] = $y;
print "before global destruction...\n";
The circular references are not necessarry for this to happen. One of the objects checks if it can access another object. If the access fails, an exception is thrown.
h2h, Matthias
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With