第13回
エラーメッセージと対処方法(3)~開発手順の効率化

論理的なエラーへの対処

コンパイルとリンクの段階でエラーがなく、実行ファイルが無事に生成できたとしても、それを実行したときに思わぬ動作をすることがあります。プログラムの設計に起因する『論理的なエラー』です。これへの対処を考えてみましょう。

変数の値を調べる

綴り間違い以外のミスで最も多いのは、稼働中のプログラムの状態を読み間違えたことによるバグでしょう。プログラムの仕様やその使われ方などによって、間違いの種類もその症状も様々なので、こればかりは具体例を挙げて「このようなときにはこうする」と、言い切ることはできません。

ただ、はっきりしているのは『プログラムの状態とは変数の値のことである』ということです。プログラムは変数を使えるからこそ、その時々の状態に合わせて柔軟に動作できます(関数の返す値も、変数の値の範疇に入ります)。

そして、この『柔軟さ』がバグを呼び込むことになります。ですから、柔軟さを支えている変数の値を見ていけば、それが設計時に意図した内容どおりに変化しているのか、あるいはそうでないのかによって、論理的な間違いの原因を見つけることが可能です。

デバッガは虫退治の補助具

バグを見つけてその対処を行うためのツールがデバッガ(debugger)ですが、デバッガが勝手に虫退治してくれる訳ではありません。ユーザー(プログラマー)がデバッガを使ってソース中の怪しい箇所を見つけ、その部分を手直ししなければなりません。

デバッガもどんどん高機能になっていますが、結局のところプログラムの実行を一時停止したり、状態を過去にさかのぼらせたり、再実行したりしながら、変数(配列、構造体やクラスなど複雑なデータ構造も含む)の値を逐一確認し、必要なら値を差し替えたりできることがデバッガの機能です。

本当に自動的に虫退治をしてくれるデバッガがあれば言うことはないのですが、まだまだ夢物語。結局は人間が頭を使って推理し、試行錯誤しながら虫探しをしなければなりません。デバッガはそれを助けるための道具でしかありません。

手軽なprintfデバッグ

Visual C++のような統合環境では、いわゆるデバッグモードでプログラムを実行すればデバッガが起動し、そこからプログラムの実行を制御しながら必要な箇所で変数の値を表示して調べたり、値を書き換えたりできます。

しかし、コマンドライン版のコンパイラを使っている場合、デバッグ・オプション ※1 を与えてソースをコンパイルした後、別途デバッガを動かさなければなりません。コマンドライン版のデバッガはいわゆるCUI ※2 なので、操作も面倒で手間がかかります。

簡単なプログラムでは、わざわざデバッガを使ってバグを探すより、必要なときにprintf関数で変数の値を表示させる方が簡単です。俗に「printfデバッグ」などと呼ばれている方法です。

LSI-C 86ではコンパイラ・ドライバLCCに-gオプションを与えれば、実行ファイルにシンボル名や行番号などデバッグ用の情報が埋め込まれます。この情報は、Microsoft社のSYMDEB(コマンドライン版シンボリック・デバッガ)で利用できます
キャラクタベースのユーザーインターフェイス(Character-based User Interface)。プロンプトに対してキーボードから文字でコマンドを入力し、その結果も文字で表示される──というスタイル