Проблема конкатенации перегрузки perl (".") - PullRequest
0 голосов
/ 22 января 2019

Пожалуйста, помогите мне понять, почему счетчик ссылок увеличивается на каждую конкатенацию?Я возвращаю тот же объект в перегруженном сабе и ожидаю, что 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;

Протестировано под

  • 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

1 Ответ

0 голосов
/ 22 января 2019

Как и задержанное сообщение 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";

Выход (до 5.28):

Exiting scope...
DESTROY
Global destruction...

Выход (5.28.0 и 5.28.1):

Exiting scope...
leak!
Global destruction...
DESTROY

Сообщите, используя утилиту командной строки perlbug.
Отчет об ошибке можно найти здесь .
Имеетсябыло исправлено в 5.30.Это может быть исправлено в 5.28.2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...