Ответ 1
use warnings FATAL => 'uninitialized';
use Carp ();
$SIG{__DIE__} = \&Carp::confess;
Первая строка делает предупреждение фатальным. Следующие две причины вызывают трассировку стека, когда ваша программа умирает.
Как вы можете заставить Perl остановиться и дать трассировку стека, когда вы ссылаетесь на значение undef, а не просто на предупреждение? Кажется, что use strict;
для этой цели недостаточно.
use warnings FATAL => 'uninitialized';
use Carp ();
$SIG{__DIE__} = \&Carp::confess;
Первая строка делает предупреждение фатальным. Следующие две причины вызывают трассировку стека, когда ваша программа умирает.
Вместо грязной игры с %SIG
, предложенной всеми остальными, просто use Carp::Always
и сделайте.
Обратите внимание, что вы можете вводить модули в script без изменений источника, просто запустив его с помощью perl -MCarp::Always
; кроме того, вы можете установить переменную среды PERL5OPT
в -MCarp::Always
, чтобы она была загружена, даже не изменяя вызов script. (См. perldoc perlrun
.)
Включите это:
use Carp ();
Затем включите одну из этих строк в верхней части исходного файла:
local $SIG{__WARN__} = \&Carp::confess;
local $SIG{__WARN__} = \&Carp::cluck;
Строка confess
даст трассировку стека, а строка cluck
намного более кратка.
Ссылка на значение undef не будет проблемой сама по себе, но может вызвать предупреждения, если ваш код ожидает, что он будет чем-то иным, чем undef. (особенно если вы пытаетесь использовать эту переменную в качестве ссылки на объект). Вы могли бы поместить что-то в свой код, например:
use Carp qw();
[....]
Carp::confess '$variableName is undef' unless defined $variableName;
[....]
Один из способов сделать эти предупреждения фатальными - установить обработчик сигнала для виртуального сигнала WARN:
$SIG{__WARN__} = sub { die "Undef value: @_" if $_[0] =~ /undefined/ };
Вам нужно сделать это вручную. Вышеупомянутые "ответы" не работают! Просто проверьте это:
use strict;
use warnings FATAL => 'uninitialized';
use Carp ();
$SIG{__DIE__} = \&Carp::confess;
my $x = undef; # it would be enough to say my $x;
if (!$x->{test}) {
print "no warnings, no errors\n";
}
Вы увидите, что разыменование не вызывало сообщений об ошибках или предупреждений. Я не знаю, как заставить Perl автоматически обнаруживать использование undef в качестве недопустимой ссылки. Я подозреваю, что это так по дизайну, так что автовивитация работает без проблем.