in reply to Unpredicted late destruction

The last example is easily explained (except you overloaded the name 'fn' which makes your code harder to read, distracting it from the real problem).

You function returns an object, which is a reference to the lexical variable $fn. (Not, not that lexical variable $fn, the other one). $x goes out of scope when leaving fn, but $fn (right, the other one) doesn't, as there's still a reference to it. In the for loop, the reference to $fn (the other one) is aliased to $fn (right, that one). It isn't until the end of the loop that $fn (that one) is no longer an alias for a reference to $fn (not that one, the other one). At that moment, there's no reference to $fh (the other one) anymore, so the object is destroyed.

Next time, please pick some none colliding variable names.

Abigail

Replies are listed 'Best First'.
Re: Re: Unpredicted late destruction
by broquaint (Abbot) on Nov 05, 2003 at 17:55 UTC
    Update: ack, this appears to be a pre-5.8.0 bug as it's fine after 5.8.0 e.g
    shell> perl5.8.0 pmsopw_304778.pl loop: pre buh-bye: sub buh-bye: sub loop: inside buh-bye: for loop: inside buh-bye: for loop: post

    Perhaps this is a better illustration of the problem

    sub DESTROY { print "bye: @{$_[0]}\n"; } sub f { my $funcobj = bless["sub"]; return 1; } print "loop: pre\n"; for( f(), f() ) { print "loop: inside\n"; my $forobj = bless ["for"]; } print "loop: post\n"; __output__ loop: pre loop: inside bye: for loop: inside bye: for bye: sub bye: sub loop: post
    So $funcobj, which one would assume to be GCed upon the exit of f(), sticks around until the end of the for loop regardless of the fact that nothing is referencing it.
    HTH

    _________
    broquaint

      Thank you for the great example of a minimal failure case! And thanks for determining that this has already been fixed :)

      I've discovered that the same problem exists for functions called in an if expression as well. Adding the following test to the bottom of your script does the wrong thing in 5.6.1 but the right thing in 5.8.0:

      print "if: pre\n"; if (f()) { print "if: inside\n"; my $ifobj = bless ["if"]; } print "if: post\n";
      Interestingly (to me, anyway), there didn't seem to be a problem with while() clauses:

      print "while: pre\n"; while (f()) { print "while: inside\n"; my $wobj = bless ["while"]; last; } print "while: post\n";
      This does the right thing on 5.6.1.

      Thanks again!

      Alan

Re: Re: Unpredicted late destruction
by ferrency (Deacon) on Nov 05, 2003 at 17:51 UTC
    You're right- the last example is a straightforward case of things working exactly how I should've expected them to. I think I shouldn't have tried to toss that example together at the last minute as I did, because now that I look at it, it's obvious why it's doing what it's doing: the object still exists.

    Not only that, when I change "return $x" to "return $fn", $x is destroyed Before the body of the for() loop, which disproves my contention that this is happening to All lexically scoped variables in functions called in a for() LIST.

    So now I guess I'd just like an idea of why filehandles aren't closed when I'd expect them to be :)

    Sorry about the variable names.

    Thanks,

    Alan