7

gcovツールの出力を理解しようとしています。オプションなしで実行することは理にかなっていますが、ブランチカバレッジオプションを試して理解したいと思います。残念ながら、ブランチが何をしているのか、なぜブランチが取得されないのかを理解するのは困難です。以下はメソッドの出力です(最新のLLVM / Clangビルドを使用してコンパイルします)。

function -[TestCoverageAppDelegate loopThroughArray:] called 5 returned 100% blocks executed 88%
        5:   30:- (NSInteger)loopThroughArray:(NSArray *)array {
        5:   31:    NSInteger i = 0;
       22:   32:    for (NSString *string in array) {
branch  0 taken 0
branch  1 taken 7
        -:   33:        
       22:   34:    }
branch  0 taken 4
branch  1 taken 3
branch  2 taken 0
branch  3 taken 3
        5:   35:    return i;
        -:   36:}

これを介して5つのテストを実行し、nil、空の配列、1つのオブジェクトを持つ配列、2つのオブジェクトを持つ配列と4つのオブジェクトを持つ配列を渡しました。最初のケースでは、ブランチ1は「ループに入る」ことを意味していると推測できますが、ブランチ0が何であるかはわかりません。2番目のケースでは、ブランチ0が再びループスルーしているように見え、ブランチ1がループを終了し、ブランチ3がループを続行/終了しているように見えますが、ブランチ2が何であるか、なぜ/いつ実行されるかはわかりません。

誰かがブランチ情報を解読する方法を知っているか、それが何を意味するかについての詳細なドキュメントを知っているなら、私は助けていただければ幸いです。

4

1 に答える 1

3

Gcov は、(コンパイル中に) マシン コマンドのすべての基本ブロックを計測することによって機能します (アセンブラーについて考えることができます)。基本ブロックとは、コードの線形セクションを意味し、内部に分岐もラベルもありません。したがって、基本ブロックの実行を開始した場合にのみ、基本ブロックの終わりに到達します。基本ブロックは、基本ブロック間の関係を示す CFG (制御フロー グラフ、有向グラフと考えてください) で編成されます (V1 から V2 へのエッジは V1 が V2 を呼び出し、V2 は V1 によって呼び出されます)。したがって、profile-arcsコンパイラと gcov のモードは、すべての行の実行カウントを取得し、基本ブロックの実行をカウントすることでこれを行います。グラフの基本ブロック間には代数関係があるため、CFG のエッジの一部は計測され、一部は計測されません。

ObjC の構造 (for..in) は、いくつかの基本ブロックに下げられます (初期のコンパイルで変換されます)。したがって、gcov は 4 つの分岐を認識します。これは、低下した BB しか認識しないためです。この低下については何も知りませんが、すべてのアセンブラ命令に対応する行は知っています (これはデバッグ情報です)。したがって、ブランチは CFG のエッジです。

基本的なブロックを確認したい場合は、コンパイル済みプログラムのアセンブラー ダンプを実行するか、バイナリーを逆アセンブルするか、コンパイラーから CFG をダンプする必要があります。profile-arcsこれを for モードと非モードの両方で実行し、profile-arcsそれらを比較できます。

profile-arcsモードには、「__llvm_gcov_ctr」や「__llvm_gcda_edge」などの多くの呼び出しとインクリメントがあります。これは、基本ブロックの実際の計測です。

于 2011-08-15T12:19:43.023 に答える