Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re^2: when is destroy function called

by 7stud (Deacon)
on Mar 02, 2013 at 07:05 UTC ( #1021393=note: print w/ replies, xml ) Need Help??


in reply to Re: when is destroy function called
in thread when is destroy function called

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


Comment on Re^2: when is destroy function called
Download Code
Re^3: when is destroy function called
by Athanasius (Monsignor) on Mar 02, 2013 at 08:19 UTC

    Sorry, my bad. I added use warnings to my copy of ggoebel’s script; forgot that it wasn’t in the original; and then compounded the confusion by referring to the warning which results as an “error’. The warning in question is:

    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,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re^3: when is destroy function called
by Anonymous Monk on Mar 02, 2013 at 08:34 UTC

    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

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1021393]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (17)
As of 2014-07-23 19:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (151 votes), past polls