簡単RPG講座 番外編。 デバッグ入門

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

簡単RPG講座 番外編。 デバッグ入門

投稿記事 by softya(ソフト屋) » 14年前

さて、みなさんは日頃どんな方法でデバッグされているでしょうか?
デバッグの方法と言っても色々とありますが、今回は簡単で効果的なデバッグ手法をご紹介します。
バグさんからのツッコミがあったのでデバッグの心得を書き添えます。

[table=border:1px;background:#FFFFFF;padding:2px 12px 2px 12px;solid #cccccc;][tr=text-align:center;]
[td=border:1px;solid #cccccc;]
●デバッグの心得
[/td]
[/tr][/table]

CODE:

ひとつ。バグの原因は自分にあると思うべし(ライブラリやコンパイラのバグを疑う前に自分を疑え)。
ひとつ。バグがないと思っているコードを疑うべし(作った時からバグ無く動いて見える関数とかはとても怪しい)。
ひとつ。if/while/for文の分岐をすべて網羅するテストを実施せよ(無理矢理でもよいので必ず分岐を通しておくとバグが表面化します)。
ひとつ。バグをねじ伏せる事なかれ(偶然直ったバグは実は直っていないことが多いので、かならず原因を説明できるレベルまで追い詰めること)


●printfデバッグ
主にコンソールアプリで使われる手法ですが、WindowアプリやDXライブラリのゲームでも利用可能です(後述)。

[table=border:1px;background:#FFFFFF;padding:2px 12px 2px 12px;solid #cccccc;][tr=text-align:center;]
[td=border:1px;solid #cccccc;]
●その1。値をprintf
[/td]
[/tr][/table]
値の変化が意図したものかを確認するために使用します。
特にポインタ値を%pで出力する事はポインタ理解が深まるのとポインタ操作の間違いを発見しやすくなるのでお勧めです。

サンプル。

CODE:

int *data = malloc( sizeo(int)*10 );
for(i=0;i0);	//数値が0より大きくなくいてはいけない。0以下ならDebugBreak();する。
●問題点の絞り込み
上記の応用でもあるんですが、どこでおかしくなっているのか絞り込む方法です。

[table=border:1px;background:#FFFFFF;padding:2px 12px 2px 12px;solid #cccccc;][tr=text-align:center;]
[td=border:1px;solid #cccccc;]
●1。分割法
[/td]
[/tr][/table]
バイナリサーチと同じ考え方を使う方法です。
プログラムの半分ぐらいでpirntfなどで状態を確認して、前と後ろのどちらに原因があるか切り分けます。
そして、後ろか前か分かったらそのまた半分の位置で原因を絞り込んでいきます。

[table=border:1px;background:#FFFFFF;padding:2px 12px 2px 12px;solid #cccccc;][tr=text-align:center;]
[td=border:1px;solid #cccccc;]
●2。縮小法
[/td]
[/tr][/table]
ソースコードをコピーして、別プロジェクトに移します。
そこでバグに関係ない処理を次々に確認しながらコメントアウトしていきます。
どんどん処理を除いていってバグが出なくなった処がバグの原因ポイントか間接的なバグ原因です。

[table=border:1px;background:#FFFFFF;padding:2px 12px 2px 12px;solid #cccccc;][tr=text-align:center;]
[td=border:1px;solid #cccccc;]
●3。配列や動的メモリのサイズ問題
[/td]
[/tr][/table]
大体のやっかいなバグは配列の添字外アクセスや動的確保メモリのポインタで起きるということに着目した手法です。
まず、配列や動的メモリを倍のサイズにしてみます。
これで単純なミスならバグが出なくなることが良くあります。
これはバグを取ったのではなくバグを表面化しなくしただけですので何も問題は解決していません。
なので、添字チェックやポインタのチェックなどを怪しい処理の前にMACRO_ASSERTで埋め込みます。
これで大体燻り出せるはずです。

[table=border:1px;background:#FFFFFF;padding:2px 12px 2px 12px;solid #cccccc;][tr=text-align:center;]
[td=border:1px;solid #cccccc;]
●4。変数の初期化問題
[/td]
[/tr][/table]
これも多いパターンでローカル変数や動的確保メモリの初期化し忘れに着目した手法です。
この場合は、ローカル変数や動的確保メモリに使ったら必ずエラーになりそうな値を必ず埋め込んでやります。
memcpyでもかまいませんので、0x11とか適当な値を入れてやるだけでかまいません。
偶然動いていたバグを燻り出せる手法でもあります。

[table=border:1px;background:#FFFFFF;padding:2px 12px 2px 12px;solid #cccccc;][tr=text-align:center;]
[td=border:1px;solid #cccccc;]
●5。関数テスト
[/td]
[/tr][/table]
関数だけを切りだして、その関数の入出力テストを行う方法です。
できればテストは自動で行いたいので入力値と出力値は机上計算で求めておいて、その値と比較するのが望ましいです。

以上です。
如何でしょう?お役に立ちそうですか?
リクエストをいただけば、またこの様な企画もやってみたいと思います。
ではまた。

参考としてVC++のデバッガの使い方のリンクも張っておきます。
「デバッガの使い方」
http://ext-web.edu.sgu.ac.jp/koike/semi/VC2005/c17.html
「デバッグ入門 [VC++の使い方]」
http://www.nitoyon.com/vc/tutorial/debug/
最後に編集したユーザー softya(ソフト屋) on 2013年8月16日(金) 11:32 [ 編集 4 回目 ]

コメントはまだありません。