開発者として、gdb を使用してコード内のバグを追跡するにはどうすればよいでしょうか? 生活を楽にするために、どのようなテクニックを使用しますか?
7 に答える
いくつかのヒント:
- グラフィカルなフロントエンドを使用します (kdbg は非常に優れています。ddd は少なくともコマンドライン gdb よりも優れています。kdevelop には優れた gdb フロントエンドがありますが、いくつかの bgs があります。nemiver も非常によく見えますが、まだ作業中です)。
- すべての重要な部分 (独自のコードといくつかのシステム ライブラリ) のデバッグ シンボルとソース コードがあることを確認してください。
- RedHat では、-debuginfo パッケージをインストールして、シンボルとソース コードの両方を魔法のようにデバッガーに表示することができます。libc 関数呼び出しなどを調べることができるため、非常に優れています。
- Debian/Ubuntu では、-dbg パッケージをインストールしてシンボルを取得できます。システム パッケージの適切なソース ファイルをインストールするのは難しいようですが、
- 私は assert() と abort() の呼び出しを、到達してはいけない場所、または調査したい場所 (ある種の重いブレークポイント) に追加する傾向があります。
- 理想的には、assert() または abort() 呼び出しは、デバッグ リリースでのみ有効にするメソッドまたはマクロでラップする必要があります。さらに良いのは、特定の環境変数が設定されている場合にのみ有効にすることです。
- SIGSEGV と SIGABRT のシグナル ハンドラーをインストールします。個人的には、ハンドラーをインストールする前に特定の環境変数が設定されているかどうかを確認します。そしてハンドラーで、通常は ~/.local/bin/ のどこかにあるハードコードされた外部コマンドを実行します。そのコマンドは kdbg を起動し、クラッシュしているアプリにアタッチする可能性があります。ほら、アプリが何か悪いことをした瞬間にデバッガーがポップアップします。
- 単体テストを使用する場合は、テスト ケースが失敗するたびにデバッガーを同様にアタッチして、アプリを検査することができます。
gdbの特に便利な機能の1つは、クラッシュしたプログラムの最終状態を検査する機能です。
クラッシュダンプ(またはより一般的に呼ばれるコアファイル)を検査するには、次のようにgdbを起動します。
gdb <program-name> <core-file>
例えば:
gdb a.out core
コアファイルでこのコマンドを実行すると、gdbはプログラムがどのように終了したかを通知し、プログラムのどこでエラーが発生したかを表示します。
Program terminated with signal 11, Segmentation fault.
#0 0x08048364 in foo () at foo.c:4
4 *x = 100;
上記の例では、ポインタに値を割り当てようとしているときに、プログラムがセグメンテーション違反で終了したことがわかります。backtracegdbのプロンプトで(またはbtまたは)と入力whereすると、プログラムの完全なバックトレースを表示できます。
(gdb) backtrace
#0 0x08048364 in foo () at foo.c:4
#1 0x0804837f in main () at foo.c:9
この時点で、に値を割り当てようとしているときに、4行目でmain()
呼び出されfoo()
てクラッシュしたことがわかります。多くの場合、これはバグを修正するのに十分な情報を提供します。foo()
*x
一般に、本来あるべきではないものを見つけ、その理由がわかるまで逆方向に作業します。
関数または行番号にブレークポイントを設定し、コードを 1 行ずつ見ていくのが最も便利です。
もう 1 つの便利なヒントは、gdb 内からこれらの関数を実行できるため、プログラムで使用されていない場合でも、すべての構造体/オブジェクトに対して show 関数を使用することです。
gdb> p show_my_struct(struct)
My custom display of Foo:
...
ウォッチポイントも非常に便利ですが、プログラムの速度が大幅に低下する可能性があります。これらは、変数またはアドレスの値が変更されたときにフローを中断します。
gdb> watch foo
Watchpoint4: foo
gdb>
私は多くの並列プログラム開発を行っているので、python / rubyで単純なラッパーを使用して、すべてのノードのすべてのプロセスにgdbをアタッチし、私に連絡することが非常に役立つことがわかりました(私はしていません)誰かが知っているなら、スレッドを乗っ取らないで、より良い方法を見つけました...)
OPの経験がわからないので、次のようにします。
GDBのドキュメントは非常に優れており、すべてが網羅されています。最初の章は、すべての基本の良い入門書です。
http://www.gnu.org/software/gdb/documentation/
gdbではありませんが、それらは関連しています。私は個人的に、どのステートメントがエラーであるかを判断するのに役立つように複雑な行を分解することが役立つことを発見しました。
また、Valgrind(http://valgrind.org/)は、バッファオーバーフローなどに取り組むのに非常に便利で便利です(これを行うためのgdbの運はありませんでした。
基本的ですが非常に便利です-オプション-tuiを指定してテキストGUIを使用します。
Geanyも使用できます。
gdb のビジュアル フロントエンドである ddd を使用します。マウスを数回クリックするだけで簡単に実行でき、コードがどのように機能するかを視覚化できます。また、デバッガー コンソールには対話型の gdb があります。