New class of memory leaks inaugurated by Perl v5.40 (and we are unprepared for that)

The following script leaks memory in perl v5.40, and it did not in v5.38:

use Scalar::Util 'weaken';
my $z;
{
    my $x;
    my $y;
    my sub my_sub {
        $x = shift;
        return sub { $y };
    };
    my $subscriber = {};
    $subscriber->{foo} = my_sub($subscriber);
    weaken($z = $subscriber);
}
say 'leak = ', int defined $z;

While Devel::Gladiator will tell you there’s a memory leak somewhere in your code, the tools I use to investigate leakage of individual objects (such as Devel::Cycle) pretend there’s no cycle in $subscriber.

While the perldelta of 5.40 does mention something changed in closure behavior, IMO it’s not clear what the new behavior exactly is, and what we should consider if we want to avoid leaks.

  1. Is this a bug in v5.40? Does it look like a bug to you? Should it be reported in github?
  2. Do Devel::Cycle and its brothers need to be updated to handle these cases too? Should issues be opened to those modules?
  3. What’s the new “rule”? I can’t figure it out by experimentation no matter how much I tried. Can someone please explain to me?

Thanks.

4 Comments

Good find.

Sorry about that.

Cannot see a circular reference here, so probably a bug.

Leave a comment

About karjala

user-pic I'm a Perl developer.