デバッガ gdb と GUI ddd を用いた C, Java プログラムのデバッグ

目次 解答例(ないかも)

最後の更新は次の時刻以降のはず.Time-stamp: "2003/03/25 Tue 10:22 hig"

プログラムの実行を命令1個ずつ追跡して誤りを見つけることのできる デバッガというものを使ってみましょう. ここでは, ddd というグラフィカルインターフェイスを通して gdb というデバッガを使います. 実は java にも jdb という デバッガがあり, ddd を通して使えます.

ddd はフリーですが, インストールされていないシステムも多いと思います. 類似のグラフィカルインターフェイスとして, xxgdb があります. これもフリーで, 普及がより進んでいます.

デバッグするためのコンパイル方法

デバッガで調べられるのは, コンパイルエラーは出なくなったけど, 実行するとsegmentation fault したり, 期待した結果が得られないようなプログラムです.

現在取り組んでいて コンパイルはできるけど segmentation fault するプログラム, またはサンプル dbgtest1.c を用意しましょう. これを -g オプションをつけてコンパイルします.

	s1609h017% cc -g -o dbgtest1 dbgtest1.c     
です. Makefile の中では, CFLAGS に -g を追加すればよいでしょう (これまでの例ではすでにそうなっていると思います).

ddd の起動

ソースファイル dbgtest1.c, 実行ファイル dbgtest1 があるディレクトリで,

	s1609h017% ddd dbgtest1 &      
で起動します. あるいは,
	s1609h017% ddd &      
として ddd を起動し, メニューバーの左端にある File メニューの Open Program... でdbgtest1を選びます.

ddd の操作1 (segmentation fault の理由を探ろう)

まず, 右図のコマンドツールが現れていることを確かめましょう. なければ, メニューバーの左端から3番目のView から, Command Tool ... を選びます.

プログラムの実行を始めるには, コマンドツールの中から Run を選びます. コマンドライン引数や標準入力を与えたい場合, Program>Run...で与えられます.

ダイアログボックスでコマンドライン引数を与えることもできます. しばらくすると, segmentation fault が起った地点 (その場所か, それ以前の地点がおかしい) が矢印で示されます.

何がおかしいかは, その付近の変数の値を調べてみるとわかるかもしれません. 値を知りたい変数の上にマウスカーソルを持っていきましょう. 値が表示されます. ただし, これは, 矢印が指している地点での値です. マウスカーソルが指す行を実行していたときの値ではありません. 今の場合, 何がおかしかったか考えてみましょう.

ddd の操作2(seg fault しないけど動作の怪しいプログラムを探ろう)

こんどは, segmentation fault しないけど, 動作のおかしいプログラムを調べてみましょう.

まずブレークポイント, すなわちプログラムを一時停止させたい点 を設定しましょう. 真ん中のソース(プログラム)が表示されている部分で, 怪しいかなと思っている点(のちょっと手前)を左クリックします. そして, メニューバー2段目左から3番目の Break をクリックすると, 赤い STOP マークがつきます. これを繰り返して, 怪しい場所すべてにブレークポイントを設定しましょう.

次にプログラムの実行を始めましょう. コマンドツールの Run をクリックします. するとプログラムが開始され, 赤いマークに矢印が重なって停止します. この状態で, 変数の値がおかしくないか調べましょう.

十分調べて, ブレークポイントが不要になったら, そのブレークポイントをクリックして, メニューバー2段目3個目で Clear (削除) できます. ドラッグすると移動できます.

おかしくないようなら, 実行を続けることにしましょう. 実行を続けるには, コマンドツールの中には, 次のような選択肢があります. 基本は Continue, Next, Step です. 特に, Next を繰り返し使うと, プログラムの実行の実際の流れを知ることができます.

Stepプログラムファイル上で処理の流れにしたがって1行進む. 関数なら, 関数の中に進む.
StepiStep の変種.
Nextプログラムファイル上で流れにしたがって1行進む. 関数なら, 関数を1行と見なす.
NextiNext の変種.
Untilプログラムファイル上で1行進む. たとえループになっていても, ファイル上の次の行にくるまで進む.
Finish実行中の関数の終りまで進む.
Cont(inue)次のブレークポイントまで進む.
Killプログラムの実行を終了する.
Up現在実行中の関数を呼び出した関数に移る
DownUp した後で元に戻る

ddd の操作3(無限ループの場所と理由を探ろう)

プログラムがいつまでも終了せず, 無限ループに入っていることが疑われる場合があります. この場合は, ddd で Run しておいて, すこし時間がたたら, コマンドツールから Interupt (割り込み) してみましょう. そのとき実行している点で停止し, 変数の値などを調べられます.

ddd の操作4(ddd でハッピーになろう)

ddd には他にもいろいろ楽しい操作があります. 試してみましょう. また, emacs 好きな人は, emacs の中から gdb を使うこともできます. ESC-x gdb [enter] してみましょう.

ddd で java をデバッグ

s1609h017% javac -g Program.java
s1609h017% ddd --jdb Program
でいいはずです. 操作はほぼ同じです. 試してみてね.

課題21_01(ta101)ステップの実際

次のプログラム
dbgtest2 または dbgtest3 をデバッガにかけ, TA の人が指定する点で プログラムを停止させ, TA の人が指定する変数を表示しよう. 場合によっては, 数ステップ実行しよう. あるいは, このプログラムでなく, 作成中のプログラムでもよい.

課題21_02(ta130)デバッグの実際

プログラム
dbgtest3 は, anim2d3 を完成させようとしたものですが, 誤りが含まれています. TA の人の気分になって, このプログラムがおかしいことを, デバッガを使って説得しましょう.
Copyright © 2002,2003 Saburo Higuchi. All rights reserved.
Saburo HIGUCHI, hig mail address