4

有两种情况我的代码不会导致分段错误

  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;
}
  • 现在我知道我可以用List::MoreUtils::natatime 替换 each_pair(虽然我听说这有一些错误),他们最近才允许这个模块进入我们的环境,我仍然对这个调用为什么会导致感兴趣分段错误——或者其他 Perl 程序员由于调试分段错误而导致的错误。

我在这方面浪费了一些时间。


编辑

我有其他模块使用此功能,有些人希望能够使用$aand $b,它也在同一模块的其他地方工作,用于另一个列表。我可以更改对它的调用,我可以为这个文件更改它,但是为每个成功使用它的地方更改它,可能比我在这么晚的时间允许做的更改更多。

4

5 回答 5

4

至于一般调试步骤,您总是可以在gdb. 看到任何有教育意义的东西的机会并不一定那么热,但我已经做过几次,甚至可能有一次帮助。

于 2009-07-23T16:36:01.643 回答
4

分段错误在 Perl 中极为罕见。我不记得我最后一次遇到一个。

调试器具有足够的侵入性,因此代码在此处的行为会有所不同也就不足为奇了,尽管这肯定令人沮丧。Smart::Comments使用源过滤器(众所周知)是邪恶的。查看 Smart::Comments 的源代码,我发现它使用了 List::Util,它通常使用XS实现。这可能List::Util是“解决”您的问题的原因。尝试List::Util直接使用但不使用Smart::Comments. 这不会解决任何问题,但它可能会将源滤波器的不确定性排除在等式之外。

不幸的是,您的问题似乎不在于代码本身,而在于不同事物之间的意外交互。您不能真正在 Perl 中直接触发分段错误。根必须在 perl 本身或 XS 代码中。如果您可以将其减少到一个小而完整的样本,其他人可能能够重现并隔离问题。

于 2009-07-23T17:35:57.700 回答
3

我将回应混乱对该功能的关注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__
于 2009-07-23T15:57:07.150 回答
3

段错误可能来自与 XS 绑定的 C 编写的外部模块中的内存错误。

我建议在valgrind中运行脚本以发现错误:

valgrind perl ./yourfaultyscript.pl
于 2009-07-24T16:39:05.287 回答
2

好吧,我不明白你为什么each_pair()这样做:

my $caller  = caller();
my $aref    = qualify( 'a', $caller );
my $bref    = qualify( 'b', $caller );

或这个:

    no strict 'refs';
    local ( $$aref, $$bref ) = @pair;

在段错误情况下,需要您关闭的引用操作strict refs似乎立即受到怀疑。

如果禁用所有这些会发生什么?

于 2009-07-23T15:20:54.227 回答