2012-06-04 25 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