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

时间:2010-12-15 22:01:36

标签: 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}; 
}

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

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

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

我的问题有两个:

  1. 为什么Perl声明$result未定义,前面有一些保护代码确保 定义
  2. 当没有数字gt时,为什么Perl会抱怨数字gt。与此警告相关联的量规确实表明Perl可能会优化您的代码,而警告会指向优化的运算符,但这是否意味着!=被“优化”为>和{{1 }}?

3 个答案:

答案 0 :(得分:8)

perl的版本是什么?

给出

use strict; use warnings;

my $x;

if ( $x ) {
    print "here\n";
}
elsif ( $x > 1 ) {
    print "there\n";
}

perl 5.10.1正确输出:

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

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

This postthis entry in perltodo似乎相关:

  

消除警告中的错误行号

     

此代码

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

用于产生此输出:

  Use of uninitialized value in numeric eq (==) at wrong.pl line 4.
  Use of uninitialized value in numeric eq (==) at wrong.pl line 4.
     

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

     

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

elsif
     

会产生此输出

   1. use warnings;
   2. my $undef;
   3.
   4. my $a = $undef + 1;
   5. my $b
   6. = $undef
   7. + 1;
     

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

     

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

     

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

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

答案 1 :(得分:2)

上的数字gt(>
elsif($observation_time->epoch() > $self->{end_threshold}) {

这是与第67行的elsif相关联的if。也许警告消息的行号错误。 $observation_time->epoch()$self->{end_threshold}可能未定义吗?

答案 2 :(得分:0)

可能是>子句中的elsif。检查这些值。