[OT] blessed sub-refs in the symbol table

Matt Lawrence matt.lawrence at virgin.net
Fri Feb 1 11:42:54 GMT 2013


On 01/02/13 09:21, Nicholas Clark wrote:
> On Thu, Jan 31, 2013 at 11:12:30AM +0000, David Cantrell wrote:
>> I am most disappointed to find that if you put a blessed sub-ref in the
>> symbol table and then replace it, its DESTROY method doesn't get called
>> straight away:
>>
>> package Immortal;
>>
>> sub new { return bless sub { print "called the object\n" }, shift; }
>> sub DESTROY { print "called DESTROY\n"; }
>> 1;
>>
>> $ perl -MImmortal -e '*Foo::bar = Immortal->new(); Foo::bar(); *Foo::bar = sub {print "blargh\n"}; Foo::bar();'
>> called the object
>> blargh
>> called DESTROY
>>
>> looks like the blessed sub continues to exist right to the end of the
>> process, even though all references to it have gone away.  Is this a bug?
> Yes, in as much as it's an optimisation that goes too far. The internals cheat
> to avoid copying subroutines (that as not closures). So, it's the same
> reference each time. Even if you bless it:
>
> $ perl -MImmortal -le 'print Immortal->new() for 1 ..3'
> Immortal=CODE(0x100818088)
> Immortal=CODE(0x100818088)
> Immortal=CODE(0x100818088)
>
> The right solution probably involves unwinding this optimisation, either
> making CVs cheap to clone, or putting in another level of indirection so
> that the addresses (and the part that you bless) are not shared, but the
> expensive stuff is.
>
There are other strange effects of this optimisation, e.g. applying 
different attributes to similar anonymous subroutines.

Can anyone enlighten me as to why this seems to fail with scalars?

# bless a SCALAR ref and stick it in the symbol table
*foo = do { bless \(my $x = "Message one"), "Foo" };
sub Foo::DESTROY { say "Goodbye, cruel world" };

say *foo{SCALAR};
# Foo=SCALAR(0x8bb46c0)

*foo = \"Message two";
say $::foo;
# Message two

say *foo{SCALAR}
# SCALAR(0x8ba7f20)
# So the original $::foo is gone, but no DESTROY yet

Matt


More information about the london.pm mailing list