Подтвердить что ты не робот

Как я могу полностью удалить пакет в Perl?

Как вы полностью удаляете пакет на Perl? Это означает не только переменные пакета, но и любые волшебные таблицы, которые Perl обновляет для обработки изменений наследования и других вещей.

Этот простой тест:

use warnings; use strict;
use Test::LeakTrace;
use Symbol 'delete_package';

leaktrace {
   package test;
   our $x = 1;

   package main;
   delete_package 'test';
};

выводит следующий результат:

leaked ARRAY(0x81c930)  from /lib/perl5/5.10.1/Symbol.pm line 166.
leaked HASH(0x827760)   from /lib/perl5/5.10.1/Symbol.pm line 166.
leaked SCALAR(0x821920) from /lib/perl5/5.10.1/Symbol.pm line 166.

Использование флага -verbose для leaktrace приводит к экранированию данных, которые я могу отправить по запросу.

Все ухудшается, если в пакет test добавлена ​​строка our @ISA = 'main';:

leaked ARRAY(0x81cd10) from so.pl line 32.
leaked SCALAR(0x81c930) from so.pl line 32.
leaked ARRAY(0x8219d0) from so.pl line 32.
leaked HASH(0x8219c0) from so.pl line 32.
leaked SCALAR(0x8219b0) from so.pl line 32.
leaked HASH(0x8219a0) from so.pl line 32.
leaked SCALAR(0x821970) from /lib/perl5/5.10.1/Symbol.pm line 161.
leaked HASH(0x821950) from so.pl line 32.
leaked SCALAR(0x821940) from so.pl line 32.

Строка 32 - это где our @ISA.

Чтобы проиллюстрировать, что это действительно утечки, а не только шум от интерпретатора:

my $num = 0;
while (1) {
    no strict 'refs';
    @{$num.'::ISA'} = 'main';
    delete_package $num++;
}

будет потреблять память с постоянной скоростью

Итак, есть ли лучший способ избавиться от пакета, чем Symbol delete_package? Есть ли что-то еще, что я должен сделать, чтобы помочь ему?

Я видел такое же поведение в 5.8.8, 5.10.1 и 5.12

4b9b3361

Ответ 1

Итак, это ошибка в perl, о которой сообщалось, даже когда вы обнаружили. За исключением фиксации, кажется, что ваш единственный способ избежать этих утечек - это выбрать другой подход для решения вашей проблемы.

Почему вам нужен полу-анонимный пакет, а не, например, закрытие? Они достаточно легки, чтобы не просачиваться, и с некоторым творческим потенциалом вы все равно можете реализовать практически все внешние интерфейсы поверх них, например, благословляя ваши кодовые блоки и предоставляя им методы, обеспечивая перегрузку для них и т.д.