8

だから私は、卒業間近の博士課程の学生から受け継いだこのプログラムのデバッグに取り組んでいます。とにかく、それをデバッグするのは私の責任です。このプログラムは基本的に、いくつかのテキスト ファイルを取り込んで処理します。私が経験した問題 (segfault) は、プログラムがまだ初期化されていない配列にアクセスしようとするために発生します。プログラムを実行して、プログラムがダウンする2つの異なるパスを比較できるデバッグツールがあるかどうか疑問に思っていました。プログラムを手動で実行することもできると思いますが、それはかなり大規模であり、まだ習得していないため、実行したくありません。私は GDB と Valgrind を使用してきました (警告を表示するために g++ -wall も使用しています)。

4

3 に答える 3

5

これらの提案は GCC に固有のものです。カバレッジ ツールを使用してgcov、プログラムのどの部分がどのくらいの頻度で実行されたかを詳細に把握できます。処理するための適切なインストルメンテーションと出力を生成するには、いくつかの特別なオプションを GCC に渡す必要がありgcovます。

--coverage このオプションは、カバレッジ分析用にインストルメント化されたコードをコンパイルおよびリンクするために使用されます。このオプションは、-fprofile-arcs -ftest-coverage(コンパイル時) および-lgcov(リンク時) と同義です。詳細については、これらのオプションのドキュメントを参照してください。

次に、プログラムを実行すると、プロファイリング データとカバレッジ データが生成されます。その後、呼び出しgcovてその出力を分析できます。以下は、上記のリンクから取得した出力の例です。

         -:    0:Source:tmp.c
         -:    0:Graph:tmp.gcno
         -:    0:Data:tmp.gcda
         -:    0:Runs:1
         -:    0:Programs:1
         -:    1:#include <stdio.h>
         -:    2:
         -:    3:int main (void)
         1:    4:{
         1:    5:  int i, total;
         -:    6:
         1:    7:  total = 0;
         -:    8:
        11:    9:  for (i = 0; i < 10; i++)
        10:   10:    total += i;
         -:   11:
         1:   12:  if (total != 45)
     #####:   13:    printf ("Failure\n");
         -:   14:  else
         1:   15:    printf ("Success\n");
         1:   16:  return 0;
         -:   17:}

-finstrument-functionsプログラムの呼び出し履歴をログに記録するために独自のインストルメンテーションを実装する場合は、GCC で およびその関連オプションを使用できます。

-finstrument-functions
関数への入り口と出口のためのインストルメンテーション呼び出しを生成します。関数の入り口の直後と関数の出口の直前に、現在の関数のアドレスとその呼び出しサイトを使用して、次のプロファイリング関数が呼び出されます。(一部のプラットフォームで__builtin_return_addressは、現在の関数を超えて機能しないため、それ以外の場合はプロファイリング関数で呼び出しサイト情報を使用できない場合があります。)

      void __cyg_profile_func_enter (void *this_fn,
                                     void *call_site);
      void __cyg_profile_func_exit  (void *this_fn,
                                     void *call_site);

最初の引数は、現在の関数の開始アドレスであり、シンボル テーブルで正確に検索できます。

C++ では、これらのフックの実装を として宣言する必要がありますextern "C"。関数が呼び出されるたびにログを記録するフックを実装できます。関数名は取得できませんが、後でポインタを後処理することができますobjdumpまたはaddr2line.

于 2013-06-21T16:51:03.650 に答える
3

GDB では、プログラムを 1 行ずつ「ステップ実行」できます。いくつかのヒント:

  1. main でブレークし (タイプb main)、n+ Enter キーを押して現在の行を実行し、次の行に移動します。
  2. 関数にステップ インするには、 + Enter キーを押しsます (つまり、呼び出された関数に移動し、そこから先に進みます)。
  3. タイプp+変数名を入力して値を出力します(その変数が初期化されているかどうかを確認するのに本当に良いです、ヒントヒント...)
  4. コマンドラインから GDB を実行していて、そのための GUI ラッパーが必要な場合は、Emacs を使用してください。emacs program.cと入力し、Alt + x次に と入力しgdbます。実行可能ファイルの名前を入力し、Enter キーを押します。これで、より多くのコードを表示でき、引き続き gdb コマンドを使用してデバッグできます。
于 2013-06-21T16:51:33.373 に答える