デバッグの作業はプログラミング以上に大変なものです。しかし、「デバッガ(デバッグツール)」というアプリケーションを使えばこの作業が簡単に出来ます。
簡単に出来るというより、問題点を発見しやすいと言った方が正しいでしょうか。
今回は私(藤原)が愛用している「Microsoft Visual C++」に付属しているデバッガを例に使い方を説明します。
他のデバッガでも大方の使い方は同じだと思います。但し、UNIXのgccなどはコンソールベースのデバッグとなるためある程度は大変だと思います(^_^;
こんな時はあせらずじっくり原因を探しましょう。
プログラムを見るだけで原因が分かれば儲ものです。しかし、どう考えても分からないときがあります。
ポイント:どう考えても原因が分からないときほど単純なミス(演算子を打ち間違えたり変数名を間違えたり)が多いものです。
この時はデバッガを使いましょう!
これは今回作成したプログラムです。
キーボードから数値を入力し、その計算結果を画面に表示するだけの単純なプログラムです。「こんなプログラム、うまく動くさ」と思っていたのもつかの間、
エラー発生!!!
しかし、このプログラムを作ったプログラマーは原因がまったく分からなかったとします。
ここで、デバッガの登場です!
手順1:デバッガを利用する前提条件
まず、Visual C++ でプログラムを組む時、「Win32 debug」「Win32 release」という2つの設定を見たことがあると思います。(「アクティブな構成の設定」というやつです。)これは現在作っているプログラムの作成モードみたいなものでして、「Win32 debug」の場合はデバッグする際に必要になる情報が実行ファイルに追加記録されます。よって「Win32 debug」モードで作成したプログラムは「Win32 release」モードで作ったプログラムよりもかなり大きなファイルとなります。しかし、デバッグを行う際は「Win32 debug」にする必要があります。プログラムを配布するとき初めてファイルサイズを小さく出来る「Win32 release」で実行ファイルを生成するようにしましょう!
手順2:デバッグモードでプログラムを実行する
デバッグモードとはデバッガの機能を使っている状態のことを言います。
上の図のように、「ビルド」→「デバッグの開始」→「ステップイン」として「ステップイン」を実行します。
手順3:デバッグモードの画面
表示される画面構成を説明します。まず、プログラムソースに黄色い矢印が表示されます。
これは現在のプログラムの実行位置を示しています。今回は実行したてなのでmain関数のすぐ下にあります。
右のほうには小さなダイアログが表示されました。このダイアログのボタンを押すことでデバッグを進めていきます。
手順4:デバッグを1行ずつ進める
コマンドダイアログの「ステップオーバー」というボタンを押すごとに黄色い矢印が1つずつ進みます。すなわち、1行ずつプログラムが実行されます。
下のウィンドウには変数名と変数の内容が表示されます。この画面を見ることで変数の値の変化を楽しむ(笑)ことができます。この値が変な風に変わった時、プログラムの「その行がおかしい」ということが判断できます。
右の画面には現在左の画面に表示されていないものを含めて自分で変数名を登録することが出来ます。また、「クイック ウォッチ」というコマンドダイアログのボタンを押すことでも変数の値を見ることが出来ます。なお、配列の場合は「プラス」ボタンが表示されますのでこのボタンを押すと配列の内容を一つ一つ表示してくれます。
また、トドメに、このウィンドウを使って変数の値を自分で好き勝手に変更することも出来てしまいます。「この値になれば正常に動くはずなのに」という事を実験したい場合に試してください。
※注意
今回のようにキーボードからの入力を促すような関数が入っている場合、実行を進めていくとその部分で止まってしまいます。
これは、実行画面で「入力待ち」を行っているためです。
この時は「コマンドダイアログ」から離れて実行画面の方を処理してください。
手順5:エラーの原因箇所発見!
1行ずつ実行していくと、scanf関数のところでエラーが起こりました。今回はどうやらここが怪しそうです。
今回はメモリ関連のエラーなので変数のポインタ/アドレス関係を頭に入れて原因を探ります。
手順6:とりあえずデバッグを中止する
「コマンドダイアログ」に「デバッグの中止」ボタンがありますからそれを押して終了させます。
今回こんな画面が出てきました。これはおそらくscanf関数内部(か、それよりもさらに内部)だと思われます。
超上級者でなければこんな所を調べても仕方がないので、このウィンドウは閉じてください。
すると、自分で作ったプログラムのソースコードの画面が表示されます。
手順7:プログラムソースを再検討
もう一度、エラーの起こったscanf関数を眺めてみます。
すると、なんとアドレス演算子が抜けていることが判明しました。
正しいプログラムに書き直してもう一度デバッグモードで実行してみましょう。
手順8:デバッグ完了
もう一度実行してみるとちゃんとscanf関数のところは成功してくれました。
結果も思い通りの値が出力されたのでデバッグを終了します。
「Microsoft Visual C++」のデバッガの機能について
今回は単純な操作例しか教えませんでしたが、実際にはいろいろなことが出来ます。
例えば、「ブレークポイント」という印をプログラム中の必要な箇所に付けておき、「ビルド」→「デバッグの開始」→「ステップイン」ではなく「ビルド」→「デバッグの開始」→「実行」とするとその印のところでプログラムを中断することが出来ます。中断したら楽しい、変数の値の調査が出来ます。
また、プログラムを1行1行進める方法にもステップイン、ステップオーバー、ステップアウトといったいくつかの種類があり特徴があります。
・ステップイン ・・・ 関数が現れたとき、その関数内に移動します。
・ステップオーバー ・・・ 関数が現れたとき、その関数は実行されたものとして次の行に進みます。
・ステップアウト ・・・ 今実行している関数から抜け出します。
例えば、memcpy関数など自分で作った以外の関数の場合はステップオーバーを選んでください。でないと、アセンブラのコードが表示されるか訳の分からない関数の内部へ入ってしまいます。
「コンテキスト」とは実行している関数で、他の関数の様子も場合によっては見ることが出来ます。
「コールスタック」とは、関数が関数を呼ぶようなプログラムのとき、どういう呼ばれ方をして現在に至っているかを表示します。
KERNEL32なんとかという関数も表示されますが、これはWindows上で動かすプログラムはmain関数ではなくそれよりも低レベルな関数から始まっていることを示しています。
あと、CPU内部の「レジスタ」やメモリの内容も表示されますが、上級者でない人には縁がないと思います。
「混合モード」はC言語の処理とそれに対するアセンブラコードが同時に表示されます。これでアセンブラを勉強するのもいいかもしれませんね(笑)