2012-06-04 56 views
1

我认为PERL(CentOS内核2.6.18-308.8.1.el5上的5.8.8)给我一个误报'未初始化变量'的警告。我所有的搜索都会产生合法的未初始化值问题。也许我也是,如果是这样的话,那么解释发生了什么(以及如何正确地做我正在做的事情)将是非常棒的。我还查看了很多hex()引用和正确的函数参数成语,并且我认为我正确地做了所有这些。“未初始化值”假阳性

我的脚本读取2个文本文件:一个包含32位硬件地址,另一个包含从该地址读回的32位数据。每个文件中的值始终为8位十六进制数字,并且两个文件都是100%匹配的(地址文件中的第1行对应于数据文件中的第1行)。当数据值不为零,一切都很好,但是当数据值是0我得到警告:

Use of uninitialized value in string eq at ../VMetro_Parser.pl line 248. 
Use of uninitialized value in hex at ../VMetro_Parser.pl line 250. 

相关代码:

sub ppReg_TX_Mode_Reg { 
    my($data) = @_; # first arg should be the Data field 
    my $ret = "\t"; 
    if($data eq "00000000") { print "TX_Mode_Reg got 0 input\n"; } #LINE 248 
    #croak("data not defined!") unless defined $data; 
    my($hex) = hex($data); #LINE 250 

    $ret .= sprintf("Clear INTs: %02X ",   (($hex >> 25) & 0x7F)); 

输入产生预期的行为:

PERL脚本
Address: 90000004 
Data: 00000004 

输出:

90000004 00000004 -> Wr TX00 Mode_Reg 
    Clear INTs: 00 

输入产生意想不到的“未初始化的值”警告:

Address: 90000004 
Data: 00000000 

PERL脚本的输出:

90000004 00000000 -> Wr TX00 Mode_Reg 
TX_Mode_Reg got 0 input 
    Clear INTs: 00 

显然,它是认识参数传递中为字符串“00000000”,但它也认为它是undef(如果我取消注释,croak行会触发)。是什么赋予了?

一个有趣的事情是有数据的其他实例为0,但不会引发警告。这些其他0数据由不同的函数处理,并且在引发警告的行之后发生,但处理过程是相同的(除了上面代码中明显的调试操作,仅由于警告而添加)。

E.G.

sub ppReg_RX_Master_Mode_Reg { 
    my($data) = @_; # first arg should be the Data field 
    my $ret = "\t"; 
    my($hex) = hex($data); 

不会发出任何警告。

+0

在你声称的输出中没有警告?!?! – ikegami

+2

该语言的名称是“Perl”。这不是一个缩写。 – ikegami

+2

'使用Devel :: Peek qw(Dump);转储($ data);'(在比较之前)可能有启发性。 – ikegami

回答

1

正如所料,问题出在我的代码而不是Perl :) 我正在使用调度表来调用我的处理函数。 Dispatch Table定义中的拼写错误导致函数在Perl处理表的声明时被调用。

违规代码:

# 'Dispatch table' is a hash for functions 
my %regPPFn = (
     TX_Version_Reg => \&ppReg_TX_Version_Reg, 
     TX_Mode_Reg => \&ppReg_TX_Mode_Reg, 
     TX_Run_Reg => \&ppReg_TX_Run_Reg, 
     ... 
     # Note: GCs are mostly TXs, so mostly call the TX fn()s 
     GC_Version_Reg => \&ppReg_TX_Version_Reg, 
     GC_Mode_Reg => &ppReg_TX_Mode_Reg, 
     GC_DMA => \&ppReg_GC_DMA, 
     GC__Reg => \&ppReg_GC__Reg, 
     "" => sub { print "Dispatch table NULL lookup\n" } 
     ); # Array of pointers to register Pretty Print functions 

你可以看到,* GC_Mode_Reg *函数引用缺少符号前的反斜杠。

GC_Mode_Reg => &ppReg_TX_Mode_Reg, 

应该

GC_Mode_Reg => \&ppReg_TX_Mode_Reg, 

使用数据::自卸车是一个伟大的第一步,让我上了轨道,表明我的函数被调用一次它“可能永远不可能被称为前”。使用$ | = 1也帮助我相信输出的文本顺序;我曾想过在我的印刷报告之前出现的警告信息是由于缓冲。

由于解决方案与最初的假设/问题标题相去不远,请告诉我如果您认为我应该编辑此问题。我不愿意改变它,因为有同样问题的其他人可能会像我一样在错误的地方看。

1

这不太可能是Perl的问题。

请记住,警告将发送到STDERR,而您的输出将发送到STDOUT。这两个不一定是同步的,所以你不能将警告和输出记录在同一记录中。

它可能有助于使用printdie而不是croak,以便警告以正确的顺序显示。

我建议你改变你的子程序

sub ppReg_TX_Mode_Reg { 
    my ($data) = @_; 
    do { warn 'Undefined $data parameter'; return; } unless defined $data; 

    . . . 
} 

,这样的代码是不是无效数据执行。

您的问题很可能出现在从文件记录中提取数据的代码中。你是否正确处理空行?如果您需要帮助,请显示这部分代码。

+1

添加'$ | = 1;'(禁用标准输出缓冲)也可以帮助解决这些问题。 – ikegami