Каковы хорошие методы или шаги для устранения ошибки сегментации в Perl?

В двух случаях мой код не вызовет ошибки сегментации:

  1. Когда я использую Smart:: Comments хотя бы в одном месте
  2. Запустите через отладчик.

Я отследил это до этого звонка:

$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 ситуации.

Что произойдет, если вы отключите все это?

Другие вопросы по тегам