Mmhh, interesting ... well the first thing to notice is the warning perl
creates about useless use of reference constructor. This indicates
that you are creating a reference to an anonymous subroutine (the outer one)
but actually you are doing nothing with it. The strange thing is that perl
does not complain about the inner one ... I have no idea why!
Ok, so let's change this a bit
{
my $subref;
{
my $foo = Foo->new;
$subref = sub { # outer
print "FOO: $foo\n";
};
}
print "Outside!\n";
$subref->();
}
Now perl produces no more warning because we save the
(outer) anonymous sub in a variable. The destroy method
is called correctly as I deleted the inner sub. The closure
we created is working as expected, producing the output:
Outside
FOO: Foo=HASH(0x1a7eefc)
DESTROY CALLED at xx line 15.
In the second step we put the inner closure back in like
this:
{
my $subref;
{
my $foo = Foo->new;
$subref = sub { # outer
print "FOO: $foo\n";
sub { # inner
print "FOO: $foo\n";
};
};
}
print "Outside\n";
$subref->();
}
What happens now is mainly guessing on my part - so please
correct me if I'm wrong. The inner closure is not handled
like the outer closure by perl (e.g. no warning). It seems,
perl doesn't know how to deal with these nested closures. In
this case, the inner one could be completely ignored as
there is no reference to the anonymous sub created and so
the object could be destroyed once $foo leaves the scope.
But perl wants to be on the safe side and does not destroy
the object until the end of the program. That could be
called a memory leak ...
Maybe someon with more knowledge about the perl internals
could shed some light on this ...
Update: Thanks to crazyinsomniac I now see the light :) The reference to the inner anonymous subroutine is - as it is the last statement in a subroutine - implicitly returned. That's the reason why perl doesn't complain...
-- Hofmator
|