2009-11-05 70 views
3

我正在清理生产版本的Perl代码,并在Apache错误日志中遇到了一个奇怪的警告。为什么Perl会在我的CGI脚本中抱怨“使用未初始化的值”?

它说:

[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; 
} 

那么,为什么未初始化变量的警告,因为它清楚地初始化?

+2

你怎么知道你通过什么这个功能呢? – 2009-11-05 14:35:56

+7

在计算机编程中,“清楚”,“明显”和“直截了当”等词语具有讽刺意味。你说他们的那一刻,情况正好相反。这是宇宙的规律。 – 2009-11-05 15:43:32

+0

哪一行是404? – Ether 2009-11-05 16:05:20

回答

12

警告只是意味着$name从未填充值,你试过就可以做一个置换操作(s///)。变量的默认值未定义(undef)。

回顾您​​的脚本,$name@_获取它的值。这意味着要么是@_是空的,要么是其第一个值为undef

1

调试通过分而治之

这是很平常碰到那些“显然是不可能的”错误---乍一看。我通常试图用简单的打印语句来确认我的假设(或者从程序中获取某些信息的等效方法:对于CGI脚本,简单的打印可能会破坏头文件)。

所以,我会把如下语句

print "testing: ", defined($name)? "defined: '$name'" : "undef", "\n"; 

到代码有嫌疑的线。您可能会对可能的输出选项感到惊讶:

  • “testing:undef”---这意味着您的函数被调用了未定义的第一个参数。不太可能,但可能。您可能想要使用caller()来查找它被调用的地方并检查那里的数据。
  • 根本没有输出!也许你看错了源文件或错误的行。 (我不怀疑是这种情况,但它确实发生在我身上)。
  • “testing:defined:'some data'”--- oops。在stackoverflow上问一个问题。
+2

使用鲤鱼比较容易,因为它指出谁在侵权案件中给你打电话。您也可能想要打印到STDERR,以便它显示在错误日志中,这更易于grep。 :) – 2009-11-05 15:59:41

+0

或者:'print“testing:”,Data :: Dumper-> new([$ name],['name']) - > Useqq(1) - > Dump;' – ysth 2009-11-05 17:00:10

3

根据你的子程序需要做什么,在你使用它们之前验证你的值。在这种情况下,由于您需要$namecroak中的某些内容,如果该变量中没有内容。你会从调用者的角度看到一条错误消息,你会发现罪魁祸首。另外,你可以通过将它作为哈希查找来使条件运算符链复杂化,这也让你有机会初始化$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; 
     } 

    ... 
    } 
} 
相关问题