我正在清理生产版本的Perl代码,并在Apache错误日志中遇到了一个奇怪的警告。
它说:
[Thu Nov 5 15:19:02 2009] Clouds.pm: Use of uninitialized value $name in substitution (s///) at /home/mike/workspace/olefa/mod-bin/OSA/Clouds.pm line 404.
相关代码在这里:
my $name = shift @_;
my $name_options = shift @_;
$name_options = $name_options eq 'unique' ? 'u'
: $name_options eq 'overwrite' ? 'o'
: $name_options eq 'enumerate' ? 'e'
: $name_options =~ m/^(?:u|o|e)$/ ? $name_options
: q();
if ($name_options ne 'e') {
$name =~ s/ /_/g;
}
那么,为什么未初始化的未初始化变量的警告呢?
答案 0 :(得分:12)
警告只是意味着$name
从未填充过值,并且您尝试对其执行替换操作(s///
)。变量的默认值未定义(undef
)。
回顾一下您的脚本,$name
从@_
获取其值。这意味着@_
为空,或者其第一个值为undef
。
答案 1 :(得分:3)
根据您的子程序需要执行的操作,请在使用之前验证您的值。在这种情况下,如果在$name
,croak
中需要某些内容,如果该变量中没有内容。你会从调用者的角度得到一条错误信息,你会找到罪魁祸首。
此外,您可以通过使其成为哈希查找来丢失条件运算符链的复杂性,这也使您有机会初始化$name_option
。在您的后备情况下,您将$name_option
未定义:
use 5.010;
use Carp;
BEGIN {
my %valid_name_options = map {
$_
substr( $_, 0, 1 ),
} qw( unique overwrite enumerate );
some_sub {
my( $name, $name_options ) = @_;
croak( "Name is not defined!" ) unless defined $name;
$name_options = $valid_name_options{$name_options} // '';
if ($name_options ne 'e') {
$name =~ s/ /_/g;
}
...
}
}
答案 2 :(得分:1)
通过分而治疗进行调试
通常会遇到“显然不可能”的错误 - 乍一看。我通常尝试使用简单的打印语句来确认我的假设(或从程序中获取一些信息的等效方法:对于CGI脚本,简单的打印可能会破坏您的标题)。
所以,我会发表一个像
这样的声明print "testing: ", defined($name)? "defined: '$name'" : "undef", "\n";
进入疑似行的代码。您可能会对可能的输出选项感到惊讶: