“未初始化的价值”误报

时间:2012-06-04 19:15:13

标签: perl embedded

我认为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) );

产生预期行为的输入:

Address: 90000004
Data: 00000004

PERL脚本的输出:

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(如果我取消注释,则会发出一条曲线)。是什么给了什么?

一个有趣的事情是,有其他数据实例为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);

不会发出任何警告。

2 个答案:

答案 0 :(得分:1)

这不太可能是Perl的问题。

请记住,警告会发送到STDERR,而您的输出将发送到STDOUT。这两者不一定是同步的,所以你不能将警告与同一记录的输出联系起来。

使用printdie代替croak可能有所帮助,以便以正确的顺序显示警告。

我建议您将子程序更改为

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

  . . .
}

这样就不会对无效数据执行代码。

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

答案 1 :(得分:1)

正如预期的那样,问题在于我的代码而不是Perl :) 我正在使用Dispatch Table来调用我的处理函数。 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,

使用Data :: Dumper是让我走上正轨的第一步,并向我展示我的功能在“可能被称为”之前被调用了一次。使用$ | = 1也帮助我相信输出文本排序;我原以为在打印报表之前出现的警告信息是由于缓冲。

由于解决方案与最初的假设/问题标题相差甚远,请告诉我是否&你怎么想我应该编辑这个问题。我不愿意改变它,因为有同样问题的其他人可能会像我一样在错误的地方寻找。