develooper Front page | perl.perl5.porters | Postings from May 2006

Re: [perl #3306] DESTROY doesn't get called.

Thread Previous | Thread Next
From:
Dave Mitchell
Date:
May 1, 2006 08:38
Subject:
Re: [perl #3306] DESTROY doesn't get called.
Message ID:
20060501153813.GA2758@iabyn.com
On Mon, May 01, 2006 at 06:57:35AM -0700, Steve Peters via RT wrote:
> >     #!/opt/perl/bin/perl -w
> > 
> >     use strict;
> > 
> >     sub new {
> >         my ($class, $code) = @_;
> >         bless $code => $class;
> >     }
> > 
> >     DESTROY {
> >         print "In DESTROY...\n";
> >     }
> > 
> >     my $i    = "Hello";
> >     my $exit = main -> new (sub {});   # 1)
> > 
> >     __END__
> > 
> > This will not print anything at all, indicating that the DESTROY
> > method

> This problem still exists in bleadperl.

This occurs because of an optimisation: anonymous subs that don't capture
any outer lexicals are not cloned but are instead shared with the sub
prototype. This doesn't work well in the presence of bless, eg:

    for (1..2) {
	my $s = sub {};
	print ref($s), "\n";
	bless $s;
    }

which outputs

    CODE
    main

One possible fix would be a COW scheme: when bless tries to bless a code
ref that happens to be an anon sub prototype, a new prototype is made and
stuck in the pad for future use. But that doesn't completely solve the
problem: any existing refs to the shared protoype will get to see the
blessed version of the sub.

Of course another fix is to turn off the optimisation and always clone
subs, but that would be expensive. For example the following loop
is about 5 times slower when the optimisation is turned off:

    for (1..10_000_000) {
	my $s = sub {};
    }




-- 
Never do today what you can put off till tomorrow.

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About