Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Global destruction feature / bug ?

by liz (Monsignor)
on Apr 03, 2008 at 13:44 UTC ( #678159=perlquestion: print w/replies, xml ) Need Help??
liz has asked for the wisdom of the Perl Monks concerning the following question:

This little program produces a result that was at least unexpected by me and a few other Amsterdam Perl Mongers:
use strict; use warnings; sub Foo::DESTROY{ print "object $_[0]->[0] destroyed\n"; } my $foo = bless [ 'foo' ], 'Foo'; # notice 'my' our $bar = bless [ 'bar' ], 'Foo'; # notice 'our' END { print "END block executed\n"; }
object foo destroyed END block executed object bar destroyed
What I expected was:
END block executed object foo destroyed object bar destroyed
In other words, any objects tied to file lexicals would be destroyed at global destruction *after* the execution of the END block. But apparently, they are destroyed *before* the END block executes. This seems at least the case with 5.8.1, 5.8.5, 5.8.8. and 5.10.0.

Is this behaviour documented anywhere? If not, where would be a good place to document this (as it cost me a few days wallclock to figure this one out and many people that I've asked their expectation about this piece of code, have given the wrong answer).

The reason I'm asking, is that I'm working on some leak detection utility. In this code example, I would consider both $foo as well as $bar as having leaked, as they were not reclaimed before the program ended. Having $foo being DESTROYed *before* the END block executes, just makes things so much more complicated... ;-(

Suggestions? Comments?


Replies are listed 'Best First'.
Re: Global destruction feature / bug ?
by Corion (Pope) on Apr 03, 2008 at 13:53 UTC

    To me, this behaviour makes sense because my $foo gets reclaimed as soon as the current scope is left (main::). After the main program has ended, the END blocks fire, and after that, all global variables get cleaned up.

    Except (as I just realize) that our is not supposed to be a global(ly visible) variable and hence should be reclaimed at the same time as my $foo, that is, in my opinion before the END blocks are run.

    One more reason to avoid our IMO.

    Update: My opinion on the order of things is wrong - the order of execution/destruction of objects is exactly as it has to be because the our variable is a global variable except that the name is not visible outside the file.

      Just to play devil's advocate . . .

      The name declared by the our isn't globally visible, but the value residing in the symbol table which it refers to is a global. The only difference is the duration of the scoping of the name you're using to access it, so it's entirely reasonable that that value is destroyed along with the normal global variable cleanup pass regardless of how you're accessing it.

      (To put it another way, you would definitely be surprised if the value in the global $main::foo was destroyed just because the temporary reference to it you created with local *somepackage::foo = \$main::foo; goes out of scope.)

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

      our is not supposed to be a global(ly visible) variable and hence should be reclaimed at the same time as my $foo

      I have to disagree. our creates a lexical alias for the global variable (stored in the symbol table).

      use Devel::Peek; our $foo; Dump $foo; Dump $main::foo; __END__ SV = NULL(0x0) at 0x24bfdc4 REFCNT = 1 FLAGS = () SV = NULL(0x0) at 0x24bfdc4 REFCNT = 1 FLAGS = ()
      The alias isn't globally visible, but there's still a global variable behind it. This is how it should be. Consider this:
      use strict; { our $foo = 'foo'; our $bar = 'bar'; } { our $foo; print $foo; print $main::bar; } __END__ foobar


      our doesn't differ significantly from use vars except that the syntax is nicer and the name is only available in the local scope even though the data is global to the namespace. I think it's well documented that our $bar doesn't go out of scope until global destruction.

      I actually think the behavior of the parent program is exactly what you should expect if you read our and my carefully.

      Please don't be down on our. It's 5.8 chic. :(


        It's mostly because of that why I dislike use of our - it establishes a global variable except that I cannot get at it or change it from the outside. And in most cases I've encountered, there always comes a moment where I want/need to change a global variable. For example to add or change some configuration, or change the quote indicator from " to ' or `. And our prevents me from doing that while adding no benefit...

Re: Global destruction feature / bug ?
by moritz (Cardinal) on Apr 03, 2008 at 14:00 UTC
    I can't answer your questions, but I would expect that the compiler/interpreter is free to destroy any object that isn't used anymore.

    If you use the variable $foo in the END block, it's only destroyed afterwards.

    Since lexical variables are only accessible from their scope, it's much easier for the compiler to proof that they aren't used from somewhere else anymore. our variables could still be referenced from END blocks in other packages.

    BTW perlobj says

    Since DESTROY methods can be called at unpredictable times, it is important that you localise any global variables that the method may update.

    That's a pretty bold statement that should shouldn't rely on any particular order.

Re: Global destruction feature / bug ?
by ikegami (Pope) on Apr 03, 2008 at 19:05 UTC

    When the scope (the file) ends, the last reference to $foo is released, so it's detroyed.

    If any function (incl END) referenced $foo, it would capture the variable. In that case, there would still be a reference to the variable at the end of the file scope, so the variable will survive until global destruction.

    use strict; use warnings; sub Foo::DESTROY{ print "object $_[0]->[0] destroyed\n"; } my $foo = bless [ 'foo' ], 'Foo'; # notice 'my' our $bar = bless [ 'bar' ], 'Foo'; # notice 'our' END { $foo; print "END block executed\n"; }
    should produce
    END block executed object foo destroyed object bar destroyed

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://678159]
Approved by Corion
Front-paged by Old_Gray_Bear
[Corion]: If you cram your slides with that much information, they might work in an "offline" situation but not very well for a live presentation IMO
[ambrus]: Corion: in that case I also ask the people who rent the conference rooms to tell conference organizers about the available tech.
[Corion]: ambrus: No, you're misunderstanding. If you place content too far on the left/right/top/ bottom, people might not see it because the view is obstructed ;)(
[Corion]: In Amsterdam, the screen went down to the bottom of the stage (60cm above ground) and the seating was on the ground, meaning that the rows in the back couldn't see the bottom of slides.
[Corion]: There also were some columns that meant that maybe you couldn't see the left/right edge of a slide.
[ambrus]: Corion: Sure. I've had a course in a 50 seat lecture hall that has two fucking columns in the middle.
[Corion]: Talking about it, the top should be fairly visible in the situations I've experienced at least. The top is uncomfortable for people in the first three rows, but that's life ;)
[ambrus]: The pillars are there because this is in the 6th floor of building R of BME, which is an attic that was built in after the original building, which is also why the elevator doesn't go that high and the windows are tiny.
[Corion]: ambrus: Hehe ;) Yeah - such real life stuff is far more inconveniencing than wasting display area due to screen ratio problems :)
[ambrus]: Corion: yes, it's a bit tricky. you can try to adjust the slides live to cover only a part of the screen, but it's still hard.

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (12)
As of 2017-09-26 10:14 GMT
Find Nodes?
    Voting Booth?
    During the recent solar eclipse, I:

    Results (293 votes). Check out past polls.