【エンジニアの道は果てしない】デバッグの思考法
こんにちは。すうちです。
以前、エンジニアの仕事に関する話を書きました。
その中で重要だけど触れてない話題がありました。デバッグです。
今回は実際デバッグする際考えていることを、極力言語化してみたいと思います。
はじめに
デバッグ(Debug)とは、下記のように
デバッグの思考法
以下、デバッグの基本的な手順です。
デバッグのやり方は、使用言語やツールなど環境によって違いはありますが、以下概ねどのような環境でも適用できる考え方をあげてみました。
どこで何が起きているか
コンパイルとプログラム実行時で少し違いますが、
上記をヒントに原因を追っていきます。
コンパイル(実行ファイル作成)時に出たエラーはそれを解決しないと先に進めませんが、ワーニングも実行時に不具合が発生する可能性があります(ツール設定によって過度な警告が出る場合もあり)。
例えば、型が違う代入のワーニングはコンパイルできても期待動作にならない(例:4Byteのデータが2Byteに削られる等)ので注意が必要です。
また実行時の不具合は、デバッガ等のツールを活用して不具合発生付近のプログラム変数やメモリ状態を確認したり、ツールが使えない場合は解析ログを追加して再現試験の結果から原因を特定します。
解析結果から原因がわかった場合はそれを修正すれば良いですが、それだけで解決しない場合、以下のやり方で原因を探っていくことが多いです。
入出力の妥当性を確認する
不具合経路の関数やメソッド(オブジェクト操作)の入出力を確認することです。
どのプログラム言語においても、あるトリガ(UI操作や割り込み)によるイベント処理やデータフロー(関数やオブジェクト間のデータやり取り)が通常あります。
問題発生時に対象のイベント処理がどこまで実行されているか。関数に渡される入力や出力は期待値か(途中データが化けたりしてないか等)確認していく方法です。
入力がおかしい場合はその前。出力が期待値と違う場合はその処理が問題ある可能性が高いです。
やる事は単純ですが、問題箇所を特定するため有効な方法と思います。
差分を見る
ここで言う差分とは
等々、プログラム実行に関わる全てです。
例えば、ある問題が発生するバージョンAと発生しないバージョンBがある場合、差分を確認します。
ライブラリやツールの差分があれば双方のバージョンを合わせたり、プログラムの場合は両バージョンのソースコードを比較して差分を見ていきます。
上記は不具合現象をログから特定できない場合もコードの変更箇所から論理的に原因を追っていけるやり方です。
その意味では機能単位や目的毎にプログラム変更(バージョン管理)する事が大前提です(会社やプロジェクト単位でルールに差はありますが、変更は極力小さい単位で行ってGit等で変更履歴を残すことが良いとされています)。
一度に複数の機能を追加したり変更すると問題発生時に何が影響しているか特定難しくなるからです。
不具合発生モデルを考える
個人的には経験上これが一番有効な気がします。
差分から原因を探る場合、問題有無のプログラム差分が少ない時は良いですが、差分が多いとそれらを全て確認するのは時間を取られます。
そのため現象面やログ等の情報から考えられる不具合発生モデル(原因の仮説)をいくつか立てて可能性高いものから確認していく方法です。
不具合発生モデルを想定すると、エラー発生につながる分岐の調査範囲を絞れるので早く問題解決につながることがあります。
消去法で原因を探る
前述の仮説を立てる方法と併用する形が多いですが、原因の可能性を複数あげた場合、問題の発生条件等から原因の可能性を事前に減らす方法です。
実際に問題発生する前提条件や事前に得られた情報を整理すると、考えた不具合モデルが全て成立する場合は余りなく一つか二つに絞られることがほとんどです。
「仮説AやBは前提条件から論理的にあり得ない。でもCはありえるなあ。。」という感じです。これにより更に調査範囲を省けるので根本原因に辿り着ける可能性が高くなります。
■最後に
最近はデバッグツールは充実していて、PC上で様々な分析や調査もできるので以前と比べるとデバッグは楽になった気がします。
今回触れませんでしたが、デバッグの難易度は不具合の再現率も関係します。再現率が低い場合、極端に解析の難易度が上がります。
組込み機器はソフトウェアだけでなくハードウェアも絡むので外部要因(例:想定外の異常データが入力された等)で問題発生すると不具合の再現が難しかったり原因特定に時間を要すこともあります(たまに1週間くらい問題が解決しないことがあると、特にリリース間際は精神的によくないです。。)
過去上記に類似する問題に何回か直面しましたが、その話はまた機会があれば書きたいと思います。
数々の修羅場!?を経験されている方には目新しい話は少ないかもしれませんが、プログラムのデバッグ等に慣れてない方など、何か参考になれば幸いです。
余談ですが、バグって言う表現はあくまで人間の視点であって、プログラムは書かれた通り動いてるだけ。。。コンピュータの立場からすれば、ちゃんとプログラム書いてくれよ、がたぶん本音ですね。
最後まで読んで頂き、ありがとうございました。