perl重载连接运算符(".")问题

zdm*_*zdm 7 perl

请帮助我理解,为什么引用计数是每个连接的增长?我在重载sub中返回相同的对象,并期望refcount保持不变.但是,似乎每次perl克隆和存储对象.为什么以及如何避免这种情况?

此外,我期待,该对象将在退出范围后被销毁,但由于非零引用计数,它仅在全局销毁阶段销毁.这看起来像是内存泄漏.

#!/usr/bin/env perl

use strict;
use warnings;
use Devel::Refcount qw[refcount];

package AAA {
    use Devel::Refcount qw[refcount];

    use overload
      '.' => sub {
        print 'CONCAT, REFCOUNT: ', refcount( $_[0] ), "\n";

        # return AAA->new;
        return $_[0];
      },
      fallback => 0;

    sub new { return bless {}, $_[0] }

    sub DESTROY { print "DESTROY\n" }
}

print "--- start\n";

{
    my $o = AAA->new;

    my $s = '1' . ( '2' . ( '3' . ( '4' . ( '5' . $o ) ) ) );

    print "--- exit scope\n";
    print 'REFCOUNT: ', refcount($o), "\n";
}

print "--- end\n";

1;
Run Code Online (Sandbox Code Playgroud)

测试下

  • perl 5.28.1 x64
  • Devel :: Refcount 0.10
  • 超载1.30

产量

--- start
CONCAT, REFCOUNT: 1
CONCAT, REFCOUNT: 3
CONCAT, REFCOUNT: 5
CONCAT, REFCOUNT: 7
CONCAT, REFCOUNT: 9
--- exit scope
REFCOUNT: 6
--- end
DESTROY
Run Code Online (Sandbox Code Playgroud)

ike*_*ami 7

就像延迟DESTROY消息一样,向对象添加弱引用表示泄漏.泄漏似乎已在Perl 5.28中引入.

use strict;
use warnings;
use Scalar::Util qw( weaken );

package AAA {
    use overload
        '.' => sub { $_[0] },
        fallback => 0;

    sub new { return bless {}, $_[0] }

    sub DESTROY { print "DESTROY\n" }
}

my $w;
{
    my $o = AAA->new;
    weaken($w = $o);
    my $s = '1' . ( '2' . ( '3' . ( '4' . ( '5' . $o ) ) ) );
    print "Exiting scope...\n";
}

print "leak!\n" if defined($w);
#use Devel::Peek;
#Dump($w);

print "Global destruction...\n";
Run Code Online (Sandbox Code Playgroud)

输出(5.28之前):

Exiting scope...
DESTROY
Global destruction...
Run Code Online (Sandbox Code Playgroud)

输出(5.28.0和5.28.1):

Exiting scope...
leak!
Global destruction...
DESTROY
Run Code Online (Sandbox Code Playgroud)

请使用perlbug命令行实用程序进行报告.
错误报告可以在这里找到.
它已在5.30修复.它可能在5.28.2中修复.