Как исследовать «Попытка освободить скаляр без ссылки» - PullRequest
8 голосов
/ 27 июля 2011

Сценарий Perl (который использует множество локально написанных модулей и находится в стадии активной разработки) только что начал производить спорадические

"Попытка освободить скаляр без ссылки: SV 0xa6e685c, интерпретатор Perl: 0x96d9008 во время глобального уничтожения. "

сообщения. Это всегда повторяется, в том смысле, что определенная последовательность команд всегда создает сообщение, если оно когда-либо возникает, но мне не удалось выделить простой или отдельный случай, который выявляет его. В частности, я еще не видел его при запуске скрипта из отладчика Perl (я могу получить его при отладке скрипта, который использует IPC :: Open3 для запуска моего целевого скрипта.)

Я понимаю, что это, возможно, ошибка в Perl, но гораздо более вероятно, что это то, что я делаю, скорее всего, вокруг моих звонков в SVN :: Client; но я зашел в тупик из-за способа исследовать это, и я подумал, есть ли у кого-нибудь указатели.

Perl 5.10.0; Различные версии Fedora Linux. Я собираюсь попробовать это на Perl 5.12, но если это не проявится и там, это мне не очень поможет. Редактировать : конкретный случай, который надежно дает сообщение в 5.10, не в 5.12. К сожалению, это ничего мне не говорит.

Ответы [ 5 ]

2 голосов
/ 27 июня 2013

Поздний ответ, но я написал длинную статью об этой конкретной теме, которая должна помочь с отладкой: Страшная «Попытка освободить скаляр без ссылки» .

1 голос
/ 27 июля 2011

Я также часто сталкиваюсь с этими сообщениями (в коде, который много использует fork) и связанной с этим проблемой ошибок сегментации на этапе глобального уничтожения (то есть программа может завершиться нормально, но ошибка во время глобального уничтоженияможет сделать программу выхода с ненулевым кодом выхода).Я также не знаю, можно ли решить эти проблемы, но обычно их можно обойти.

Сначала используйте глобальную переменную, чтобы определить, находитесь ли вы в фазе глобального уничтожения:

our $_GLOBAL_DESTRUCTION = 0;
END { $_GLOBAL_DESTRUCTION = 1; }

(см. Также переменную ${^GLOBAL_PHASE}, доступную в Perl v> = 5.13.7)

Тогда избегайте запуска проблемного кода на этапе глобального уничтожения:

sub MyObject::DESTROY {
    return if $_GLOBAL_DESTRUCTION;
    ... # else proceed 
}

sub other_function_that_frees_unreferenced_scalars {
    return if $_GLOBAL_DESTRUCTION;
    ...
}
1 голос
/ 27 июля 2011

Это часто связано с проблемами потоков, особенно при передаче переменной из одного потока в подпрограмму, выполняющуюся в другом. Вот абстрактный пример шаблона:

A.pl

....
my $dummy;
threads->create("B::c", ($dummy));
....

B.pm

....
sub c{...}
....

Я понимаю, что поиск чего-то похожего на это в вашей "загрузке локально написанных модулей" будет нелегким. Возможно, вы можете вырезать фрагменты своей программы, пока не найдете что-то, что меняет поведение; это должно помочь вам изолировать проблему.

0 голосов
/ 24 января 2015

foreach (@var) - еще один хороший кандидат для проверки.

Следующий код дал мне это предупреждение:

foreach (@list1) {
    my ($i, $j) = @$_;
    my $k = get_k($i, $j);
    foreach (@$k) {
        sub_that_uses_fork($_);
    }
}

Но следующее не:

while (scalar(@list1)) {
    my ($i, $j) = @{shift(@list1)};
    my $k = get_k($i, $j);
    foreach (@$k) {
        sub_that_uses_fork($_);
    }
}
0 голосов
/ 04 ноября 2014

Проверьте наличие любых типов блочных объектов, которые ссылаются на указатели, например, типового блока для хэша хэшей.Я столкнулся с этим с помощью typeglob, который используется для переключения между разными хэшами массивов.Ошибка возникла, когда записи были удалены с использованием как typeglob, так и исходного имени хеша.Либо использование простого хэша без вложений, либо избавление от typeglob устранили проблему.

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