in reply to when is destroy function called
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 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:
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:
#! perl use strict; use warnings; $| = 1; #--------------------------------------------------------------------- +--------- package Phaser; sub new { my ($class, $name) = @_; my $self = {}; $self->{name} = $name; return bless $self, $class; } #--------------------------------------------------------------------- +--------- package Dalek; sub new { my ($class, $phaser_ref) = @_; my $self = {}; $self->{phaser} = $phaser_ref; return bless $self, $class; } sub exterminate { return 'Firing phaser ' . $_[0]->{phaser}->{name} . "\n"; } sub obey { return 'obey'; } sub DESTROY { my ($self) = @_; print 'DESTROYing a Dalek (phaser is ', $self->{phaser}->{name}, " +)\n"; $self->{phaser}->{name} = 'Obliterator'; } #--------------------------------------------------------------------- +--------- package main; my $phaser = Phaser->new('Exterminator'); my $enemy = Dalek ->new($phaser); print 'My enemy is a ', ref $enemy, ' with a phaser named ', $phaser->{name}, "\n"; print $enemy->exterminate(); print 'My enemy must ', $enemy->obey(), undef($enemy), '. His phaser is named ', $phaser->{name}, eval('$enemy->exterminate()'), ". Bye!\n"; print $@ if $@; print 'The phaser is named ', $phaser->{name}, "\n";
Output:
16:59 >perl 552_SoPW.pl My enemy is a Dalek with a phaser named Exterminator Firing phaser Exterminator Use of uninitialized value in print at 552_SoPW.pl line 67. My enemy must obey. His phaser is named Exterminator. Bye! DESTROYing a Dalek (phaser is Exterminator) Can't call method "exterminate" on an undefined value at (eval 1) line + 1. The phaser is named Obliterator 16:59 >
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,
Athanasius <°(((>< contra mundum | Iustus alius egestas vitae, eros Piratica, |
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^2: when is destroy function called
by roboticus (Chancellor) on Mar 02, 2013 at 15:43 UTC | |
by Athanasius (Archbishop) on Mar 02, 2013 at 17:28 UTC | |
by roboticus (Chancellor) on Mar 02, 2013 at 21:35 UTC | |
by Athanasius (Archbishop) on Mar 04, 2013 at 04:10 UTC | |
by roboticus (Chancellor) on Mar 06, 2013 at 02:37 UTC | |
| |
Re^2: when is destroy function called
by 7stud (Deacon) on Mar 02, 2013 at 07:05 UTC | |
by Athanasius (Archbishop) on Mar 02, 2013 at 08:19 UTC | |
by Anonymous Monk on Mar 02, 2013 at 08:34 UTC |