ものえおさむ

あたりまえすぎて誰も書かないデバッグのい・ろ・は。

2008-09-09 17:51:00

はじめに
このブログでは、"Windows アプリケーションってどう作るのかよくわからない" といったプログラマ向けに Visual C# 2008 Express Edition (無償) を使用した Windows アプリケーションに作り方について説明しています。
Visual C# 2008 Express Edition (無償) の入手方法については
この記事 を、プロジェクトのコンパイル方法については この記事を参照してください。

ここのところ世間では新しい携帯電話やブラウザの話題で盛り上がっていますが、そういった最新の話題とはまったく関係なく(笑)、 前回に引き続きのんびりとデバッグについて書いてみたいと思います。

今回は、デバッグをする際に誰しもが無意識にやっているであろう、デバッグの手順について書いてみたいと思います。

ちなみに私、開発業務をしていた頃もそうなのですが、開発製品のユーザーサポートをしていたともあり、そのおかげで非常にたくさんの他人の書いたコードをデバッグする機会に恵まれ(???) ました。

他人の書いたコードを、限られた時間と情報だけで、問題箇所を明確にするという業務は過酷ですがいろいろと勉強になりました。

とくに、年がら年中デバッグやらトラブルシュートなどやっていると、問題解決の微妙な勘どころというのが分かってきて、問題箇所を発見するまでのセオリーというのが自分なりにだんだんと作られてくるのです。

そういったセオリー的なものは、普段からプログラミングを行っている人であれば、その人なりのものを持っていて、普段意識せずにやっていると思うのですが、明示的にその方法と根拠を書いておけばもしかして誰かの役に立つのでは? と思ったしだいです。

ということで、問題解決までの、最大公約数的なデバッグの手順を簡単にまとめてみました。

だいたいこんな感じになると思います。

順番 作業内容
0 おちつく
1 エラーメッセージ、あるいは、意図しない動作を明確にする
2 問題の再現手順を明確にする
2.5 問題の再現可能な最少のサンプルコードを作製する
3 例外を発生されたコードの箇所を確認する
4 例外を発生箇所のコードが処理と、発生時に扱った値(データ)を確認する
エラーメッセージを参考に以下の点を確認する
  A) 処理は想定される値に対して適切なものであるか?
          ⇒ 適切な処理に変更してください
    B) 値は処理に対して適切なものであるか?
         ⇒ 5へ
5 処理に対して適切でない値に変化した箇所とその理由を調べる
⇒ 4 へもどる

各ステップごとに簡単に説明してみます。

0. おちつく
-----------
開発中のものであればエラーが発生してもそれほど問題はないのかもしれませんが、運用中のものだったりすると大きな問題になる可能性があります。
もしかしたらあなたは、このエラーが原因で上司や顧客から人格をも否定されるような罵詈雑言を浴びせられ、過剰な言葉の暴力になすすべもなくさらされるかもしれません。
しかし、あわてないでください。大丈夫、なにも死ぬわけではありません。
ここはひとつ落ち着いて、そのエラーなり、問題なりが与える影響について判断し、必要とあればしかるべきところ(※弁護士ではありません)に連絡して影響を最小限にとどめるよう努めてください。

1. エラーメッセージ、あるいは、意図しない動作を明確にする
-----------------------------------------------------
明確にエラーメッセージが表示される場合はメッセージの内容を正確に記録してください。
意図しない動作が発生する場合は、なにがどう問題なのかを明確にし、目視で確認できるような現象であれば画面ショットを取得してください。
ログが出力されるのであれば、それを確実に取得してください。
それらは問題発生の証拠であり、結果であり、その回避がデバッグの目標となります。

 

2. 問題の再現手順を明確にする
-----------------------------
100% エラーを再現させることのできる手順を明確にしてください。デバッグ作業において問題の再現手順を明らかにすることは非常に重要です。
エラーを再現できなければ、検証作業による原因の追及は難しくなりますし、目的のエラーが回避できたかどうかの判断もできません。
どのような手順で UI を操作し、どのような情報を入力したか、第三者が作業しても同様のエラーが発生できる程度の正確さで、エラーの再現手順を明確にしてください。

エラーの原因というものは、"回避できた"という事実からさかのぼってみなければ明確にならないものが数多くあります。
たとえば理論的に考えられるエラーの原因を取り除いても、実際にエラーが回避できていなければ、それが原因ということにはなりません。
そういった意味でも、"エラーの状況を明確にすること"、"エラーの再現手順を明確にすること"は非常に重要なのです。

 

2.5. 問題を再現可能な最少のサンプルコードを作製する
------------------------------------------------
状況が許せば、ぜひやっていただきたいのが、問題を再現するための必要最小コードでのサンプルアプリケーションの作成です。
目的のエラーを再現するのに関係のないコードを完全に排除して、最少のコードで問題再現のためのアプリケーションを作成してください。
最少コードで問題が再現できれば、その後のデバッグ作業が楽になりますし、サンプルアプリケーションの作成中に問題の原因が明確になり解決に至るケースは多くあります。

 

3. 例外 (エラー) を発生させたコードの箇所を確認する
---------------------------------------------------
エラー、あるいは異常動作の直接の原因となったコードを特定します。
Visual Studio IDE 上でプロジェクトをデバッグモード(※)で実行した場合、例外箇所で実行が停止し、エディタ上のコードに例外の発生箇所を示します。
例外が発生せず、意図しない動作を行う場合は、再現手順から問題の動作が発生する直前のコードにブレークポイントを設定し、ステップ実行(※)で確認するのがいいでしょう。

(エラーの発生箇所の表示)

(※) Visual Studio IDE のデバッグ機能については この記事 を参照してください。

 

4. 例外を発生箇所の処理と、発生時に扱った値(データ)を確認する
---------------------------------------------------------
処理を行ったコードブロック (多くの場合は関数) 入出力の値と、処理を確認します。
以前の 記事 にも書きましたが、プログラムの大まかな構造はすべて "入力" と" 処理" と "出力" からなっています。これは関数を表すコードプロックでも同じです。
つまり、引数(入力)と返り値(出力)の内容をチェックすれば、そのコードブロック(処理)が誤りを含んでいるか確認することができるのです。
具体的には、どのような引数を与えられた場合に(入力)、どのような返り値を返す(出力)すのかを明確にします。
仕様書がある場合は必ず、仕様書を確認してください。

(関数の引数のチェック)

エラーの再現手順に従ってアプリケーションを実行し、実際に渡されているの関数の引数の値と返り値を確認し、その両方が想定したものであるか確認します。

返り値が想定したものと異なる場合は、処理内容に誤りがあると考えられますので、ステップ実行などで処理の内容を確認し、修正してください。

引数が処理に対して適切でない場合は、呼び出し元の処理に問題があると考えられますので、呼び出し元を同様の手順でデバッグします。

 

5. 処理に対して適切でない値に変化した箇所とその理由を調べる
--------------------------------------------------------
ブレークポイントとステップ実行、ルック式などを駆使して処理をさかのぼり、入力に対し出力が想定外となるところを調査します。
調査の方法としては、手順 4 のとおりです。

あとは、手順 4 ~ 5 を繰り返していけばエラーの原因を明らかにすることができると思います。

もっとも、環境の問題などが絡むと、もっと多岐にわたる手順が必要となりますが。。

----------------
以上、今回はプログラマであるなら無意識にやっているであろうデバッグのいろはを書いてみました。

もちろんデバッグの手法は人それぞれなのでこれが正解というわけでもありません。

数多くプログラムを書いて自分なりのセオリーを身に付けていきたいですね。

次回からは、そーですねー、C# でメモ帳でも作ってみますか。

それではまた。

※マイクロソフト社員のコミュニティ参加について

※このエントリは ブロガーにより投稿されたものです。朝日インタラクティブ および ZDNet Japan編集部の見解・意向を示すものではありません。
  • 4件のコメント
#1 Jitta   2008-09-10 13:38:04
私も昔、自分のブログに書きました。悲しいのは、読む必要がある人ほど、読んでくれないこと...
私がサポートを利用するときは、「何をしたいか」も話すようにしています。コミュニティで質問に答えるときには、「何をしたいか」を聞くようにしています。コード上は問題が無く、「何をしたいか」の実現方法が間違っていることや、「何をしたいか」そのものが間違っていることがあるためです。
#2 ものえおさむ   2008-09-10 18:48:12
Jitta さん、コメントありがとうございます。

>「何をしたいか」も話すようにしています。
確かに!
それをつつがなく実現するのが究極的な目的ですものね。

>「何をしたいか」の実現方法が間違っていることや、
思わず PC の前で "あるある"と呟いてしまいました(笑
コードに誤りがなくても、方法が間違ってるとうまくいきませんから。
"バグ"って深いですよね。
#3 GAN彩坊   2008-09-18 02:39:14
灌漑深いお話でした。

現在デバッグより後の工程のテストをしているのですが、ログはいっぱい出るんですが、
肝心のどこでエラーが起こっているかをログに出してくれていなくて、
どうしていいかわかりません。

何をしたいか分かっていない人のソースを見ると、
コメントが間違っていたり、仕様とずれていたりして、

「あぁ、こりゃバグるよなって」

思ってしまいます。(人のことをいえないですが・・・)


「何をしたいか」も重要ですが、「何をしてもらいたいのか」の要求に答えられていないから
バグっているのかもしれませんね。


バグは嫌いです!
#4 ものえおさむ   2008-09-19 16:22:34
GAN彩坊 さん、コメントありがとうございます。

>「何をしてもらいたいのか」の要求に答えられていないから
今後どれほど技術が進歩しても、要求に合わせてコードを書くのは人間ですから、このテのバグってなくならないんでしょうね。
作成者の認識のズレっていうのは、仕様なり、コードの構造なりにあぶりだされてきますから。
"結局は人間"って、考えるとますますバグって深いなぁ~と思ってしまいます。

わたしもバグは嫌いです。
  • 新着記事
  • 特集
  • ブログ