Perl lexicals lifetime brokenness with nested anon subs

5.8.8 has a nasty bug in the lifetime of lexicals that are referenced in a closure that is nested within an anon sub (that doesn’t reference those lexicals). The first time the code creating the anon sub is executed the lexicals get an extra reference that never goes away (or at least not before the package goes away or something). On any subsequent runs the refcount is correct.

use strict;
use Devel::Peek;

use Devel::Peek;
use Scalar::Util;
my %ids;

sub create_sub_leaking {
    my $id=shift;
    print "leaking id $id, refcount " . Devel::Peek::SvREFCNT($id) . "\n";
    $ids{$id}=\$id; Scalar::Util::weaken($ids{$id});

    my $sub= sub {
        my $sub2= sub {
            $id;
        };
        return $sub2;
    };
    return $sub;
}

my $s1=create_sub_leaking(1);
my $s2=create_sub_leaking(2);

$s1=undef;
$s2=undef;

print "stashed 1: ";
Dump( $ids{1} );
print "stashed 2: ";
Dump( $ids{2} );

Shows the refcount on the first call being 2 and that the lexical variable doesn’t go away.

Bother.

This means I have to be really careful to reference all the necessary lexicals in all the enclosing subs to make them behave.

This is all fixed in 5.9 since 2003 but will not be backported. And I’m not quite willing to move to 5.9.

This entry was posted in CS. Bookmark the permalink.

One Response to Perl lexicals lifetime brokenness with nested anon subs

  1. Jimmy says:

    Hi Mika,

    Your blog is very cool! I’m a Symbian developer, too. Hope to be friend with you. And also welcome to my Symbian blog: http://www.symbianSIG.com. Thanks, hope to hear from you.

    BR
    Jimmy