Каковы хорошие методы или шаги для устранения ошибки сегментации в Perl?
В двух случаях мой код не вызовет ошибки сегментации:
- Когда я использую Smart:: Comments хотя бы в одном месте
- Запустите через отладчик.
Я отследил это до этого звонка:
$action->{breakdown}
= join( ' '
, each_pair {
my ( $name, $length ) = @_;
return "x$length" if $name eq 'FILLER';
push @$field_list_ref, $name;
return "A$length";
} @$field_def_ref
);
где each_pair
определяется в другом модуле как:
sub each_pair (&@) {
my $block = shift;
return unless @_;
my $caller = caller();
my $aref = qualify( 'a', $caller );
my $bref = qualify( 'b', $caller );
my @results;
my $pairs = 0;
for ( my $index = 0; $index < $#_; $index += 2 ) {
$pairs++;
my @pair = @_[$index..($index+1)];
no strict 'refs';
local ( $$aref, $$bref ) = @pair;
push @results, $block->( @pair );
}
return wantarray || $pairs != 1 ? @results : shift @results;
}
- Теперь я знаю, что могу просто заменить each_pair на List:: MoreUtils:: natatime (хотя, как я слышал, в нем есть некоторые ошибки), они только недавно пропустили этот модуль в нашу среду, и мне все еще интересно, почему этот вызов вызывает ошибка сегментации - или что другие программисты Perl из-за ошибок отладки сегментации.
Я потерял немного времени на это.
РЕДАКТИРОВАТЬ
У меня есть другие модули, использующие эту функцию, некоторые ожидают, что смогут использовать $a
а также $b
Кроме того, он работает в другом месте в том же модуле, для другого списка. Я могу изменить этот вызов, я могу изменить его для этого файла, но изменение его для каждого места, где он успешно используется, вероятно, больше изменений, чем мне было бы разрешено сделать в этот поздний час.
5 ответов
Ошибки сегментации исключительно редки в Perl. Я не могу вспомнить последний раз, когда я столкнулся с одним.
Отладчики настолько навязчивы, что не удивительно, что код будет вести себя по-другому, хотя это, конечно, расстраивает. Smart::Comments
использует исходные фильтры, которые (как мы все знаем) являются злыми. Заглядывая в источник для Smart::Comments, я вижу, что он использует List::Util, который обычно использует реализацию XS. Возможно, что List::Util
это то, что "исправляет" вашу проблему. Попробуйте использовать List::Util
прямо, но не Smart::Comments
, Это ничего не решит, но может вывести из уравнения неопределенность исходного фильтра.
К сожалению, ваша проблема не в самом коде, а в неожиданном взаимодействии разных вещей. Вы не можете вызвать ошибку сегментации непосредственно в Perl. Корень должен быть либо в самом Perl, либо в XS-коде. Если вы можете уменьшить его до небольшого, но полного образца, другие смогут воспроизвести и изолировать проблему.
Что касается общих шагов отладки, вы всегда можете запустить интерпретатор Perl под gdb
, Шансы увидеть что-нибудь познавательное не обязательно настолько высоки, но я делал это пару раз, и, возможно, даже помог один раз.
Я повторю беспокойство хаоса с each_pair
функция. Что произойдет, если вы используете следующую реализацию?
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
sub each_pair(&@);
my $field_def_ref = [ qw( FILLER 5 NOTFILLER 6 ) ];
my $field_list_ref;
print join(' ' => each_pair {
my ($name, $length) = @_;
return "x$length" if $name eq 'FILLER';
push @$field_list_ref, $name;
return "A$length";
} @$field_def_ref ), "\n";
print Dumper $field_list_ref;
sub each_pair( &@ ) {
my $code = shift;
my @results;
for my $i ( 0 .. $#_/2 ) {
push @results, $code->( shift, shift );
}
return @results;
}
__END__
Сегфаулты могут возникать из-за ошибок памяти в написанных на C внешних модулях, связанных с XS.
Я рекомендую запустить ваш скрипт в valgrind, чтобы обнаружить ошибку:
valgrind perl ./yourfaultyscript.pl
Ну, я не могу понять, почему ваш each_pair()
делает это:
my $caller = caller();
my $aref = qualify( 'a', $caller );
my $bref = qualify( 'b', $caller );
или это:
no strict 'refs';
local ( $$aref, $$bref ) = @pair;
и ссылки на операции, которые требуют выключения strict refs
кажется, немедленно подозреваемый в segfaulting ситуации.
Что произойдет, если вы отключите все это?