1

異なるマシンから gcov ファイルをマージするための perl スクリプトを作成しました。以下は、マージ用に作成したサブルーチンです。

sub merge_gcov()
    {
        open(FILE1, "<$_[0]") or die "can not open file";
        open(FILE2, "<$_[1]") or die "can not open file";
        open(FILE3, ">$_[2]") or die "can not open file";
        my ($line1, $line2 , $flag );
        while ( 1 )
        {  
            $line1 = <FILE1>; # read them each
            $line2 = <FILE2>;
            last unless ( $line1 || $line2 ); # if both empty exit loop
            #
            # otherwise test for which one just finished
            #
            unless( $line1 )
            {
                $flag = 1;
            last;
            }
            unless( $line2 )
            {
                $flag = 2;
            last
            }   
            #
            # now do the voodo on the two lines
            #
            chomp($line2);
            chomp($line1);
            if($line1=~/^\s*-/ and  $line2 =~/^\s*-/)  
            {   
                print FILE3 "$line1\n";
            }
            elsif($line1=~/^\s*#####/ and  $line2 =~/^\s*#####/) 
            {      
                print FILE3 "$line1\n";
            }
            elsif($line1=~/^\s*#####:\s{0,}(\d{1,})/ and  $line2 =~/^\s{0,}(\d{1,})/) 
            {     
                print FILE3 "$line2\n"
            }
            elsif($line1=~/^\s{0,}(\d{1,})/ and  $line2 =~/^\s*#####:\s{0,}(\d{1,})/) 
            {  
                print FILE3 "$line1\n"
            }
            elsif($line1=~/^\s{0,}(\d{1,})/ and  $line2 =~/\s{0,}(\d{1,})/) 
            { 
                my @values1 =  split(/:/, "$line1");
                my @values2 =  split(/:/, "$line2");
                print FILE3 ("      ",$values1[0]+$values2[0]),":","$values1[1]:","$values1[2]\n";
            }
            else
            {  
                print FILE3 "$line1\n";
                print FILE3 "$line2\n";
             }

        }
    close(FILE3);
    }

マージは適切に行われますが、マージ後にエラーが発生します....

Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 284046 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 284414 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 302995 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 311633 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 311962 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 321536 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 323445 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 329553 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 336009 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 336330 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 338188 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 343170 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 349037 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 349610 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 633937 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 634509 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 634877 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 653458 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 662096 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 662425 (#1)
Use of uninitialized value in concatenation (.) or string at
        ./Merge_gcov_generalised.pl line 226, <FILE2> line 671999 (#1)
Use of uninitialized value in concatenation (.) or string at

警告を使用しなかった場合、これらの警告が表示されないことはわかっていますが、これらの警告を削除する他の方法はありますか。

226 行目: print FILE3 (" ",$values1[0]+$values2[0]),":","$values1[1]:","$values1[2]\n";

4

2 に答える 2

0

いずれかの行が初期化されていないかどうかをテストしますが、その情報を使用することはないためundef、最終的な改行で連結されたものを出力していますelse。これが警告の原因です。

ファイルgcovには、実際には余分な改行がたくさんあります。これは、一致しない行ごとに 1 つのファイルが最初に不足することが原因です。それらが有効なgcovのは、受け入れる内容が非常に寛容であるかgcov、最初の裸の改行が表示されたときに入力を黙って読み取るのを停止するためです。最初は素晴らしいです。2番目は非常に悪いです。

これを修正するには、どこにあると予想されるundefか、見つけたときに何をすべきかを理解する必要があります。このコードは、各ファイルの最後に到達したときに生成さundef$line1ます。$line2これらをどのように使用して、どこundefが OK でどこがそうでないかを見てみましょう。

  1. 両方の行が false であることをテストする (例undef: ): これはundef.
  2. 設定$flag: 使用法は良いが、二度と使用$flagしないためロジックが悪い。
  3. パターン マッチ: 適切な使用法です。パターン マッチは、nothing に対して失敗する必要があり (失敗する) ため、これはコードに適しています。
  4. 可能性のある行を印刷するundef:悪い使用法。これにより、警告が生成され、余分な空の改行が出力されます。

パターン マッチは に対してすべて失敗するため、undefset するコードを完全にスキップし$flagて、最後のコードを次のelseようにすることができます。

...
else {
    # One or the other file has run out already. Note that
    # the $line variables being undef here is OK because that's
    # an expected possible value that we're actually testing for.
    # We could used "defined $lineX" but since undef itself is 
    # false, this is okay.
    print FILE3 "$line1" if $line1;
    print FILE3 "$line2" if $line2;
}

ここで、いくつかのundef哲学について説明します。

初期化されていない変数の警告は、ほとんどの場合、どこかで論理エラーが発生しますが、Perl はそれを修正してくれます。これらを取得している場合は、次を探す必要があります。

  1. を返す何かを呼び出していundefますか? もしそうなら、私はそれを間違って呼んでいますか、それとも間違ったパラメータで呼んでいますか? //呼び出しが有効な場合、0 や '' (defined-or 演算子を使用) のように、誤りなくデフォルト値を代用できますか? 代わりに、デフォルト値を提供するためにテーブルまたはサブが必要ですか? デフォルト値を使用できない場合、ロジックの何が問題になっていますか?
  2. そうでない場合、初期化されていない配列またはハッシュ エントリを参照していますか? Perl はこれらのエントリを自動有効化し、それらを に設定しますundef。インデックスまたはキーが間違っていますか? そうでない場合は、これらのエントリを自分でデフォルト値に設定し、配列のインデックスを境界チェックするか、ハッシュのハッシュ要素かどうかをチェックする必要がありexistsますか? それ以外の場合は、1. の基準が適用されます。
  3. どちらにも当てはまらない場合は、初期化されていないスカラー変数があります。なぜ初期化されないのですか?何に初期化すればいいですか?(スカラーを既知の値に初期化しないことによって)どの仮定を忘れましたか?

一般的に言えば、コードが警告を発行することになっていない限り (たとえば、コードに a を追加しwarnた場合)、警告は何かが期待どおりではないことを意味します。診断を隠すだけでなく、それを見て理由を確認する必要があります。

于 2014-09-23T03:04:50.627 に答える
0

あなたがしたいことは、あなたがすでに期待し、説明した特定の警告を取り除くことだけである場合、あなたがしなければならないことはこれだけです:

{    no warnings 'uninitialized';
     # **Small** bit of code causing the problem.
     say "A string and $probably_undefined";
}

私が強調する理由は、コードが小さいということです。Perl には、プラグマによってオンとオフを切り替える千の警告カテゴリがないからです。それにはいくつかのかなり広いカテゴリがあり、あまりにも広いスペースのために武装解除したままにしておく、噛まれます. アイデアは、警告された状態を見て、初期化されていない値が影響を与えないかどうか、または少なくとも説明できる値かどうかを判断することです。

于 2013-01-18T12:49:47.317 に答える