Почему perl сообщает неверный номер строки для этого предупреждения относительно неинициализированного значения, используемого в elsif? - PullRequest
5 голосов
/ 16 декабря 2010

Я получаю странное предупреждение против некоторого 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. Почему Perl жалуется на числовой gt, когда нет числового gt.Рубрика, связанная с этим предупреждением, указывает на то, что Perl может оптимизировать ваш код, а предупреждение относится к оптимизированным операторам, но означает ли это, что != «оптимизирован» до > и <?

Ответы [ 3 ]

8 голосов
/ 16 декабря 2010

Какая версия 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.

Эта запись и эта запись в 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. Рафаэль исправил это - проблема возникла из-за того, что между выполнением оператора if и elsif не было nextstate OP, поэтому PL_curcop по-прежнему сообщает что текущая исполняемая строка - это строка 4. Решение заключалось в том, чтобы вводить операторы nextstate для каждого elsif, хотя оказалось, что OP-оператор nextstate должен был быть операцией с нулевым состоянием, а не живым OP-оператором nextstate, иначе другие номера строк стали доложены. (Jenga!)

Проблема носит более общий характер, чем elsif (хотя случай elsif является наиболее распространенным и наиболее запутанным). В идеале этот код

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

выдаст этот вывод

   Use of uninitialized value $undef in addition (+) at wrong.pl line 4.
   Use of uninitialized value $undef in addition (+) at wrong.pl line 7.

(а не строки 4 и 5), но для этого требуется, чтобы каждый OP содержал (как минимум) информацию о номере строки.

Что может сработать, так это иметь дополнительный номер строки в памяти непосредственно перед структурой BASEOP, с битом флага в операторе, чтобы сказать, присутствует ли он. Первоначально во время компиляции каждый OP будет иметь свой номер строки. Затем добавьте поздний проход в оптимизатор (возможно, в сочетании с переупаковкой optree), который просматривает две операции на каждом краю графика пути выполнения. Если номер строки изменяется, помечает целевой пункт с этой информацией. Как только все пути прослежены, замените каждую операцию с флагом на операцию nextstate-light (которая просто обновляет PL_curcop), которая, в свою очередь, передает управление истинной операции. Все операции будут заменены вариантами, в которых не хранится номер строки. (Что, по логике, почему это будет лучше всего работать в сочетании с переупаковкой optree, поскольку это уже копирует / перераспределяет все OP)

(хотя я должен отметить, что мы не уверены, что делать это для общего случая стоит)

Вот фактический коммит . Учитывая, что фиксация произошла в апреле 2008 года, я предполагаю, что это исправление было включено в релиз 5.8.9 (см. perlhist ).

2 голосов
/ 16 декабря 2010

Там это числовой GT (>) на линии

elsif($observation_time->epoch() > $self->{end_threshold}) {

, то есть elsif, связанный с if в строке 67. Возможно, в предупреждающем сообщении указан неправильный номер строки. Может ли $observation_time->epoch() или $self->{end_threshold} быть неопределенным?

0 голосов
/ 16 декабря 2010

Это, вероятно, > в предложении elsif.Проверьте эти значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...