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) );

产生预期行为的输入:

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(如果我取消注释,就会触发 croak 行)。是什么赋予了?

一件有趣的事情是,还有其他数据为 0 的实例,但没有引发任何警告。其他 0 数据由不同的函数处理,并发生在引发警告的行之后,但处理是相同的(除了上面代码中明显的调试操作,只是因为警告而添加的)。

例如

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

不抛出任何警告。

4

2 回答 2

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,

使用 Data::Dumper 是让我走上正轨的第一步,它向我展示了我的函数在“可能被调用”之前被调用过一次。使用 $| = 1 也帮助我相信了输出文本的顺序;我曾认为在我的打印语句之前出现的警告消息是由于缓冲造成的。

由于该解决方案与最初的假设/问题标题相差甚远,因此请告诉我您是否以及如何认为我应该编辑此问题。我犹豫要不要改变它,因为遇到同样问题的其他人可能会像我一样在错误的地方寻找。

于 2012-06-05T18:56:14.807 回答
1

这不太可能是 Perl 的问题。

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

print使用anddie代替croak以正确顺序显示警告可能会有所帮助。

我建议您将子程序更改为

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

  . . .
}

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

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

于 2012-06-04T19:40:11.603 回答