david2008 has asked for the wisdom of the Perl Monks concerning the following question:
Hi all,
This is a question regarding general knowledge of the perl language.
If i undef an object and the object has a destroy function, when is this function called ?
If i have a code
use Spreadsheet::WriteExcel;
use File::Copy;
# Create a new Excel workbook
my $workbook = Spreadsheet::WriteExcel->new('perl.xls');
# Add a worksheet
my $worksheet = $workbook->add_worksheet();
# Write a formatted and unformatted string, row and column notation.
$col = $row = 0;
$worksheet->write($row, $col, 'Hi Excel!', $format);
undef $worksheet;
undef $workbook;
copy("perl.xls","perl2.xls") or die "Copy failed: $!";
The excel workbook object has a destructor which calls the close function.
Can i assume that the close function of the workbook is called before the copy call, or do i have to close the workbook explicitely?
In c++ the destructor is called right when the object goes out of scope.
In java the destructor is called when the garbage collector wants and i can not rely on it.
What happens in perl ?
Thanks,
David
Re: when is destroy function called
by tobyink (Canon) on Feb 27, 2013 at 16:53 UTC
|
use v5.14;
package Mouth {
use Moo;
has teeth => (is => 'ro');
sub DESTROY { say 'Mouth->DESTROY' }
}
package Head {
use Moo;
has mouth => (is => 'ro');
sub DESTROY { say 'Head->DESTROY' }
}
my $mouth = Mouth->new(teeth => []);
my $head = Head->new(mouth => $mouth);
say 'undefining $mouth';
# Note: DESTROY not called, because $head still refers to $mouth
undef $mouth;
say 'undefining $head';
# Now both DESTROY methods will be called
undef $head;
Compare that with the ZombieHead which allows its mouth to randomly disintegrate by using a weak reference...
use v5.14;
package Mouth {
use Moo;
has teeth => (is => 'ro');
sub DESTROY { say 'Mouth->DESTROY' }
}
package ZombieHead {
use Moo;
has mouth => (is => 'ro', weak_ref => 1);
sub DESTROY { say 'Head->DESTROY' }
}
my $mouth = Mouth->new(teeth => []);
my $head = ZombieHead->new(mouth => $mouth);
say 'undefining $mouth';
undef $mouth; # DESTROY is called!!
say 'undefining $head';
undef $head;
References can be weakened using Scalar::Util.
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Maybe this is helpful?
I don't think your first example helps answer the op's question. Did the gc destroy the objects immediately after you undefined $head or did the gc merely mark them as ready for destruction, and then when the program ended the memory was released?
Some evidence from "Intermediate Perl (2nd)", p. 257:
To do the proper cleanup operations when Perl destroys an object, we need to know when that happens. Thankfully, Perl provides such notification upon request. We can request this notification by giving the object a DESTROY method.
When the last reference to an object, say $bessie, disappears, Perl invokes that object’s DESTROY method automatically, *as if we had called it ourselves*:
$bessie−>DESTROY
This method call is like most other method calls: Perl starts at the class of the object and works its way up the inheritance hierarchy until it finds a suitable method. However, unlike most other method calls, there’s no error if Perl doesn’t find a suitable method.
That suggests that DESTROY is called immediately after the reference count goes to 0--in other words the object is not merely marked for destruction with DESTROY being called at the gc's leisure.
| [reply] [Watch: Dir/Any] |
Re: when is destroy function called
by aitap (Curate) on Feb 27, 2013 at 16:44 UTC
|
| [reply] [Watch: Dir/Any] |
Re: when is destroy function called
by ggoebel (Sexton) on Feb 28, 2013 at 04:20 UTC
|
Perl is reference counted. So unless you're writing XS or creating circular references, you don't need to pay much attention. However, for those times when you do... the destructor is called when the last reference is undefined.
the following...
package Dalek;
sub new { return bless {}; }
sub exterminate { return q{'exterminate'}; }
sub obey { return q{'obey'}; }
sub DESTROY { print "destroy\n"; }
package main;
my $obj = Dalek->new();
print "obj is a: ", ref($obj), "\n";
print "Where's my ", eval('$obj->obey()'), undef($obj), eval('$obj->exterminate()'), " spanner?\n";
print $@ if $@;
gives...
> perl destroy.pl
obj is a: Dalek
Where's my 'obey' spanner?
destroy
Can't call method "exterminate" on an undefined value at (eval 2) line 1.
Note that the object is destroyed before the print statement in the destructor is flushed to STDOUT | [reply] [Watch: Dir/Any] |
Re: when is destroy function called
by sundialsvc4 (Abbot) on Feb 27, 2013 at 18:29 UTC
|
perldoc perlobj contains a definitive discussion both of destructors and of Perl’s garbage collector. I think that the best way of thinking of both constructors and destructors is that they are “initialization” and “de-initialization” subroutines, respectively. Of the two, destructors are less commonly used because they are less commonly required: if there are no “unusual” storage-reference situations that might confuse the garbage collection algorithm, and no external resources to clean up, you often don’t need one.
As a rule of thumb, if you do something in the object’s constructor that is peculiar to that particular object instance and that has to be un-done, then you need to worry about defining a destructor. But if you simply allocated a big data-structure that’s associated with the object, no worries, because the reference-count of all those things will also go to zero when the object itself does. (Any exceptions to that rule will of course require an appropriate destructor.)
One thing that I can definitely say from very painful experience is this: that you must never leave an ambiguous situation behind when your destructor completes. If you “close” a socket, say, then immediately obliterate all memory of it (undef). This is doubly true if you are indulging in fancy-pants designs involving subclasses of any sort. Look carefully at the entire constructor and destructor sequences as your application grows.
| [reply] [Watch: Dir/Any] |
Re: when is destroy function called
by Athanasius (Archbishop) on Feb 28, 2013 at 12:25 UTC
|
The documentation in perlobj, as quoted by aitap, says:
When the last reference to an object goes away, the object is destroyed. If you only have one reference to an object stored in a lexical scalar, the object is destroyed when that scalar goes out of scope.
This can be read in two ways:
- The object’s DESTROY method (if any) is called immediately when its reference count drops to zero.
- When an object’s reference count drops to zero, it is scheduled for destruction, and the DESTROY method (if any) is called by the Perl runtime at the first opportunity.
The consensus in this thread seems to be that interpretation (1) is correct, but ggoebel has in fact provided a counterexample — notwithstanding the fact that ggoebel himself says:
Note that the object is destroyed before the print statement in the destructor is flushed to STDOUT
But I don’t believe that flushing the output filehandle plays any part here. Adding $| = 1; at the top of the code makes no difference to the output. My understanding is that in ggoebel’s example what happens is this:
- When undef($obj) executes, the value of $obj is set to undef;
- the object’s reference count is decremented to zero;
- the object is scheduled for destruction, but not yet destroyed;
- the print statement completes;
- then and only then the object’s DESTROY method is called.
That is, the error warning message indicates only that $obj is undef, not that the object to which $obj formerly pointed has been destroyed.
As evidence I offer the following adaptation of ggoebel ’s example, enhanced to give the object a resource which it modifies in its DESTROY method:
As can be seen by the change of phaser name from “Exterminator” to “Obliterator”, the DESTROY method is not called until immediately after the print statement completes.
I conclude that the documentation should be read according to the second interpretation. If this were C++, we could refer to an account of “sequence points” for a precise statement of when the DESTROY method is called. As it is, the following seems like a good rule of thumb for destructors in Perl:
When an object’s reference count falls to zero, its DESTROY method will be called immediately upon completion of the statement (not expression) in which the reference count is decremented.
In some (probably rare) cases, this might be an important distinction to keep in mind.
Hope that helps,
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Athanasius:
I lean towards the first reading. I think the reason that the destroy method executes after print completes is because a reference to the object is placed on the stack, and the reference count goes to zero when the parameters are cleared from the stack.
Calling destroy immediately is simpler than maintaining a to-do list for later processing. If I were to write perl, I'd choose the simpler method. (Of course, I can't offer any evidence either way--it's just my gut feeling.)
...roboticus
When your only tool is a hammer, all problems look like your thumb.
| [reply] [Watch: Dir/Any] |
|
roboticus:
I think the reason that the destroy method executes after print completes is because a reference to the object is placed on the stack, and the reference count goes to zero when the parameters are cleared from the stack.
So the idea is that DESTROY is called immediately when the reference count falls to zero, but that the decrementing of the reference count does not occur immediately upon the call to undef? That sounds reasonable, but I’m not sure which stack is meant. It can’t be the subroutine’s parameter list:
#! perl
use strict;
use warnings;
{
package Foo;
sub new
{
return bless {};
}
sub DESTROY
{
print "Foo::DESTROY\n";
}
}
my $foo = Foo->new();
bar($foo);
print "Back in main\n";
sub bar
{
print "Begin bar()\n";
undef $_[0];
print "End bar()\n";
}
Output:
3:14 >perl 556_SoPW.pl
Begin bar()
Foo::DESTROY
End bar()
Back in main
3:18 >
Can you clarify what you mean by “a reference to the object is placed on the stack”?
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
|
|
That is, the error message indicates only that $obj is undef, not that the object to which $obj formerly pointed has been destroyed.
First, a variable has no memory of what it was. It just knows what it is.
Secondly, I'm baffled by your explanation of the example's output. It seems clear to me that the output from the DESTROY method comes before the error message, yet you conclude that DESTROY isn't called until after the error message.
I have to admit I have no idea what the example is supposed to demonstrate with all the eval()'s, strange names, and unintelligible (English?) output. Here is my example (which seems to prove your conclusion):
use strict;
use warnings;
use 5.010;
$| = 1;
{
package Dog;
sub new { return bless {}; }
sub bark { say 'Bow wow!' }
sub DESTROY { print "destroy\n"; }
}
my $dog = Dog->new();
print 'hello',
$dog->bark(),
undef $dog,
$dog->bark(),
'world',
;
--output:--
Bow wow!
Can't call method "bark" on an undefined value at 2.pl line 17.
destroy
| [reply] [Watch: Dir/Any] [d/l] |
|
Secondly, I'm baffled ...
Nope, obey is printed before DESTROY. use the debugger, or just Devel::Trace, if you can't follow the text
$ perl -d:Trace dalek
>> dalek:4: $| = 1;
>> dalek:48: my $phaser = Phaser->new('Exterminator');
>> dalek:11: my ($class, $name) = @_;
>> dalek:12: my $self = {};
>> dalek:13: $self->{name} = $name;
>> dalek:14: return bless $self, $class;
>> dalek:49: my $enemy = Dalek ->new($phaser);
>> dalek:22: my ($class, $phaser_ref) = @_;
>> dalek:23: my $self = {};
>> dalek:24: $self->{phaser} = $phaser_ref;
>> dalek:25: return bless $self, $class;
>> dalek:51: print 'My enemy is a ', ref $enemy,
My enemy is a Dalek with a phaser named Exterminator
>> dalek:53: print $enemy->exterminate();
>> dalek:30: return 'Firing phaser ' . $_[0]->{phaser}->{name} . "
+\n";
Firing phaser Exterminator
>> dalek:55: print 'My enemy must ', $enemy->obey(),
>> dalek:35: return 'obey';
>> (eval 1)[dalek:55]:1: $enemy->exterminate()
Use of uninitialized value in print at dalek line 55.
My enemy must obey. His phaser is named Exterminator. Bye!
>> dalek:40: my ($self) = @_;
>> dalek:41: print 'DESTROYing a Dalek (phaser is ', $self->{phase
+r}->{name}, ")\n";
DESTROYing a Dalek (phaser is Exterminator)
>> dalek:42: $self->{phaser}->{name} = 'Obliterator';
>> dalek:60: print $@ if $@;
Can't call method "exterminate" on an undefined value at (eval 1)[dale
+k:55] line 1.
>> dalek:62: print 'The phaser is named ', $phaser->{name}, "\n";
The phaser is named Obliterator
unintelligible (English?)
Its perfectly intelligible , its just a bit of fiction
Here is my example (which seems to prove your conclusion)
It doesn't really, the program dies before print prints anything -- it short circuits, failing to prove that order of cleanup/DESTROY isn't immediate
On a related note about global destruction order, see sub DESTROY: Strange ordering of object destruction (global destruction order not guaranteed | [reply] [Watch: Dir/Any] [d/l] |
|
Use of uninitialized value in print at...
which comes from the inclusion of undef($obj) in the arguments to the print statement.
The evals are there to allow the print statement to complete in spite of the error (exception) which results from the attempt to call a method on an undefined object. That error is:
Can't call method "exterminate" on an undefined value at (eval 2) line
+ 1.
which in the original example was captured by the eval and printed by the statement print $@ if $@;.
I agree that your example “seems to prove” my conclusion; but I wanted to be sure. Hence my provision of an additional resource which is altered within the DESTROY method. Adapting your example:
#! perl
use strict;
use warnings;
use 5.010;
$| = 1;
my $num = 42;
{
package Dog;
sub new { return bless {}; }
sub bark { say 'Bow wow!'; }
sub DESTROY { print "destroy\n"; ++$num; }
}
my $dog = Dog->new();
print 'hello ',
$dog->bark(),
undef $dog,
eval('$dog->bark()'),
"|$num|",
"world\n";
print $num;
Output:
18:02 >perl 552_SoPW.pl
Bow wow!
Use of uninitialized value in print at 552_SoPW.pl line 31.
hello 1|42|world
destroy
43
18:02 >
which shows that $num is incremented only after the print statement completes, and not at the point where the reference count of $dog falls to zero. (Note that the “1” in the output comes from the say statement in Dog::bark, which returns true on success.)
Hope that helps,
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|