デバッグ


デバッグについて

プログラムが大規模になってくると、プログラムを書いてから1回で全く問題なく動作するというのは逆に珍しいことです。

完成後の動作確認だけではなく、通常は正しく動作するかどうか、不具合があればどこが原因かを確認しながらプログラムを作成していきます。

プログラムのミスはバグと呼ばれ、それを駆除する作業がデバッグです。

プログラムを眺めただけで発見できるバグならば良いですが、実行してみて初めて気づくものも多いです。


デバッグの例題

変数の宣言を強制せず(モジュールにOption Explicitを記述せず)に、以下のコードを書いてみてください(実行はしないでください)。おかしい点に気づくでしょうか。

 '無限ループを含むコード
Sub test_Debug1()
    Dim i As Long
    Dim count As Long
    Randomize
    While (i < 10)
        i = j + Rnd
        count = count + 1
    Wend
    MsgBox count & "回で、処理が終了しました"
End Sub

これは『 i にrnd関数の乱数を加算し、10に到達するまでの加算回数を集計する』つもりのプログラムです。rnd関数が返す値は平均約0.5弱(0以上1未満の値をほぼ等しい確率で返すので)のはずですから、感覚的には21回程度で到達するはずです。

ところで、VBAのプログラムの実行を途中で止めるには『Ctrl+Break』を使います。VBEの標準ツールバー上にも中断ボタンはありますが、実行中には押せなくなることが多いので、ショートカットは必ず覚えておいてください。

それでは中断の操作を確認したら上のコードを実行(『F5』)してみましょう。

そして実行したらすぐにショートカットで中断し、『デバッグ』を選択してください。

コードの中断

中断するとVBEが編集できる状態に成り、黄色い矢印がプログラムが今まさに実行しようとしている行(命令)を指しています。

中断時のVBE

さて、図ではWendの位置でプログラムが中断しています(デバッグ中)。

デバッグ中はカーソルを変数の上に重ねると変数の値を参照することができます。また、画面左下に配置したローカルウィンドウでも、現在実行中のプロシージャの変数を見ることができます。

ちなみに右下のウォッチウインドウでは、任意の式を設定して値を参照することができます。

いま、適当に止めた図ではcountの値が81575546になっていますが、これは予想の21回に対して大きすぎますから、何かおかしそうです。

デバッグその1 ~ すぐに気づくケース

よく見るとローカルウィンドウに j という変数があります。

使用している(つもり)の変数はiとcountだけですから、ここで間違いに気づきますね。

ループの度に i に『未定義の j(この計算式では毎回double型の0として扱われる) + RND 』を加算しているわけですから、結果としてはrnd関数の値をそのまま i に代入しているに過ぎません。

rnd関数は0以上1未満の乱数を発生させる関数なので、何回繰り返しても i は1以上にならず、条件が満たされることがないため無限ループに陥っていることが分かります。

デバッグその2 ~ ステップ実行でデバッグ

中断して変数を確認してもその時点で間違っている箇所が特定できない場合、ステップ実行により小刻みにプログラムを進めて動作を確認します。

F8』キーを押すと、黄色い矢印が1行進みます。

また、ブレークポイントを設定することにより、プログラムを中断させる位置を予め指定することができます。

ブレークポイントは入力カーソルがある行で『F9』キーを押すか、行の左の部分をクリックすることで設定/解除することができます。

乱数を取得する行にブレークポイントを設定してみました。ブレークポイントが設定されていると、『F5』で全体を実行した場合でもブレークポイントの位置で自動的に中断されますが、ここではとりあえずステップ実行してみます。

ステップ実行1

i の値は0.7485...となっていますね。それではもう一周してみましょう。

ステップ実行2

i の値が0.2837...と、0以上1未満の小数を累計加算するプログラムを書いたはずなのに前回の値よりも小さくなるのはおかしいですよね。ここで ij を間違っていたことが誤動作の原因であると気づくはずです。

デバッグその3 ~ 修正して動作確認

簡単な例でしたが、正しいプログラムに修正した後に実行して動作を確認します。

 '無限ループを修正したコード
Sub test_Debug2()
    Dim i As Long
    Dim count As Long
    Randomize
    While (i < 10)
        i = i + Rnd'jをiに修正
        count = count + 1
    Wend
    MsgBox count & "回で、処理が終了しました"
End Sub
バグを修正したコードの実行

以上でデバッグ完了です。最初は難しく感じるかもしれませんが、デバッグ作業に慣れることがプログラミング上達への近道です。間違い探しを楽しみましょう。

作成者はなかなか気づかないものが、プログラムが思い通りに動かない原因はほとんどが簡単なミスです。焦らずにコーヒーでも飲んで落ち着き、思い込みを捨てて考えるのがデバッグのコツです。