1

PERL(CentOSカーネル2.6.18-308.8.1.el5の5.8.8)は、誤検知の「初期化されていない変数」の警告を表示していると思います。私の検索はすべて、正当な初期化されていない値の問題を見つけます。おそらく私のものもそうです。もしそうなら、何が起こっているのか(そして私がやろうとしていることを正しく行う方法)の説明は素晴らしいでしょう。また、hex()の多くの参照と正しい関数の引数のイディオムを調べましたが、それらはすべて正しく行っていると思います。

私のスクリプトは2つのテキストファイルを読み取ります。1つには32ビットのハードウェアアドレスが含まれ、もう1つにはそのアドレスから読み取られた32ビットのデータが含まれます。各ファイルの値は常に8桁の16進数で、両方のファイルが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で問題になる可能性はほとんどありません。

警告はSTDERRに送信されますが、出力はSTDOUTに送信されることに注意してください。この2つは必ずしも同期しているとは限らないため、同じレコードの出力と警告を結び付けることはできません。

警告が正しい順序で表示されるようにする代わりに、を使用するprintと役立つ場合があります。diecroak

サブルーチンを次のように変更することをお勧めします

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

  . . .
}

無効なデータに対してコードが実行されないようにします。

問題は、ファイルレコードからデータを抽出するコードにある可能性があります。空白行を正しく処理していますか?ヘルプが必要な場合は、コードのこの部分を表示してください。

于 2012-06-04T19:40:11.603 に答える
1

予想通り、問題はPerlではなくコードにありました:)ディスパッチテーブルを使用して処理関数を呼び出しています。ディスパッチテーブル定義のタイプミスにより、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回呼び出されていることを示しました。$|を使用する = 1は、出力テキストの順序を信じるのにも役立ちました。印刷ステートメントの前に表示される警告メッセージは、バッファリングが原因であると思っていました。

解決策は最初の仮説/質問のタイトルからかなり離れていたので、この質問を編集する必要があるかどうか、およびどのように考えているかを教えてください。同じ問題を抱えている他の誰かがおそらく私と同じように間違った場所を探しているので、私はそれを大きく変更することを躊躇します。

于 2012-06-05T18:56:14.807 に答える