为什么perl报告了关于elsif中使用的未初始化值的此警告的错误行号?

Dan*_*umb 5 perl warnings initialization

我对一些Perl代码发出了一个奇怪的警告,我希望SO大脑可以提供帮助.

有问题的代码是:

sub add_observation {
    my $self = shift;
    my $observation = shift;

    my $result = $observation->get_datum_result($self->{datum_name});
    if(!(defined $result)) {
        croak("Datum '$self->{datum_name}' not defined for this observation: ". Dumper($observation));
    }
    $self->{result} |= $result;
    my $observation_time = $observation->get_time();

    if($self->{result} == 0){
        $self->set_start_time($observation_time);
    }
    if($result != 0) {
        $self->set_end_time($observation_time);
        $self->{end_threshold} = $observation_time->epoch() + $self->{timeout};
    }
    elsif($observation_time->epoch() > $self->{end_threshold}) {
        $self->{complete} = 1;
    }

    return $self->{result}; 
}
Run Code Online (Sandbox Code Playgroud)

当我运行我的代码时,我收到以下警告:

Use of uninitialized value in numeric gt (>) at Performance/BadSpan.pm line 67 (#1)
Run Code Online (Sandbox Code Playgroud)

第67行等同于该if($result != 0) {行.

我的问题是双重的:

  1. 为什么Perl中指出$result未定义,当有在它之前的一些后卫代码,确保它定义
  2. 当没有数字gt时,为什么Perl会抱怨数字gt.与此警告相关联的量规确实表明Perl可能会优化您的代码并且警告会引用优化的运算符,但是这是否意味着a !='被'优化'到a >和a <

Sin*_*nür 8

什么是perl

特定

use strict; use warnings;

my $x;

if ( $x ) {
    print "here\n";
}
elsif ( $x > 1 ) {
    print "there\n";
}
Run Code Online (Sandbox Code Playgroud)

perl 5.10.1正确输出:

Use of uninitialized value $x in numeric gt (>) at C:\Temp\t.pl line 8.

鉴于这elsif不是独立的,而是if声明的一部分,早期版本中可能存在一个错误,它报告了封闭if语句的行号.

这篇文章此条目perltodo似乎相关:

消除警告中不正确的行号

这段代码

  1. use warnings;
  2. my $undef;
  3.
  4. if ($undef == 3) {
  5. } elsif ($undef == 0) {
  6. }
Run Code Online (Sandbox Code Playgroud)

用于产生此输出:

  Use of uninitialized value in numeric eq (==) at wrong.pl line 4.
  Use of uninitialized value in numeric eq (==) at wrong.pl line 4.
Run Code Online (Sandbox Code Playgroud)

第二次警告线被误报的地方 - 它应该是第5行.Rafael解决了这个问题 - 问题出现了,因为在执行if和之间没有下一个OP elsif,因此PL_curcop仍然报告当前正在执行的行是第4行.解决方案是为每个注入一个下一个OP elsif,尽管事实证明,下一个OP需要是一个空的OP,而不是一个实时的下一个OP,否则其他行号被误报了.(积木!)

问题比一般情况更为普遍elsif(尽管elsif案例是最常见且最令人困惑的).理想情况下这个代码

   1. use warnings;
   2. my $undef;
   3.
   4. my $a = $undef + 1;
   5. my $b
   6. = $undef
   7. + 1;
Run Code Online (Sandbox Code Playgroud)

会产生这个输出

   Use of uninitialized value $undef in addition (+) at wrong.pl line 4.
   Use of uninitialized value $undef in addition (+) at wrong.pl line 7.
Run Code Online (Sandbox Code Playgroud)

(而不是第4和第5行),但这似乎要求每个OP都携带(至少)行号信息.

可能有用的是在BASEOP结构之前的内存中有一个可选的行号,在op中有一个标志位来说明它是否存在.最初在编译期间,每个OP都会携带其行号.然后向优化器添加一个延迟传递(可能与重新装入optree相结合),它会查看执行路径图的每个边缘上的两个操作.如果行号更改,则使用此信息标记目标OP.跟踪所有路径后,将每个op替换为带有nextstate-light op(仅更新PL_curcop)的标志,然后将控制权传递给真正的op.然后,所有操作都将被不存储行号的变体替换.(从逻辑上讲,为什么它与重新包装optree一起效果最好,因为它已经在复制/重新分配所有OP)

(虽然我应该注意到,我们不确定为一般情况做这件事是值得的)

这是实际的提交.鉴于提交发生在2008年4月,我假设修复程序包含在5.8.9版本中(参见perlhist).