ソフトウェア開発 Win32プログラミング

デバッグのこつ

戻る


デバッグ(debug)とは、プログラムのソースコードを修正して、 バグ(bug; 不具合、もともとは虫の意味)を取り除いて、 正しく動作するようにすることだ。

デバッグを行うのに使われるのが、デバッガというツールだ。 BCC55ではtd32というプログラム、GCCではgdbというプログラムがデバッガである。 VC++では、統合環境にデバッガが含まれている。

BCC55をお使いの人は、C:\Borland\Bcc55\td32read.txtを読んでほしい。 このファイルには、デバッガを使う上での注意点などが書かれている。

デバッガでソースコードをデバッグするためには、プログラムがデバッグ版で ビルドされていなければならない。BCC55ではコンパイル・リンク時に-v -yを、 GCCでは-g -ggdbを付けなければならない。VC++ではプロジェクトのプロパティで デバッグ版に設定する。デバッグ版でビルドされていれば、 ソースコードをいちいち変更しなくても、実際に実行しながら動作を確認できる。

デバッグの基本は、ソースコードの特定の位置にブレークポイント(breakpoint)を設定して、 実行させ、ブレークポイントで実行が止まったら、変数の値をデバッガのウォッチ(watch)で調べることである。

デバッグを容易にするために、Win32プログラミングでは MFCで使われているようなASSERTやTRACEマクロを以下で示すように実装することもできる。

debug.h
#ifndef _DEBUG_H_
#define _DEBUG_H_
 
#ifdef DEBUG
#define ASSERT(x) do { if (!(x)) AssertFail(__FILE__, __LINE__, #x); } while(0)
#define TRACE DebugPrintf
#else   // ndef DEBUG
#define ASSERT(x)
#define TRACE (void)
#endif  // ndef DEBUG

VOID AssertFail(LPCSTR pszFile, INT nLine, LPCSTR pszExpression);
VOID DebugPrintf(LPCSTR pszFormat, ...);
 
#endif  // ndef _DEBUG_H_
debug.cpp
#include <windows.h>
#include <commdlg.h>
#include "debug.h"

VOID AssertFail(LPCSTR pszFile, INT nLine, LPCSTR pszExpression)
{
    DWORD dwError;
    CHAR szModule[MAX_PATH], szFileTitle[256];
    CHAR szMessage[1024];
    INT id;
 
    dwError = GetLastError();
    GetFileTitle(pszFile, szFileTitle, 256);
    GetModuleFileName(NULL, szModule, MAX_PATH);
    wsprintf(szMessage,
        "プログラム: %s\n"
        "ファイル: %s\n"
        "行: %d\n"
        "式: %s\n"
        "LastError: %ld\n"
        "\n"
        "プログラムを中止するには[中止]を、\n"
        "DebugBreak()するには[再試行]を、\n"
        "続行するには[無視]を押してください。",
        szModule, szFileTitle, nLine, pszExpression, dwError);
    id = MessageBoxA(GetActiveWindow(), szMessage, "ASSERT失敗",
                     MB_ICONERROR | MB_ABORTRETRYIGNORE);
    switch(id)
    {
    case IDABORT:
        ExitProcess(-1);
        break;
 
    case IDRETRY:
        DebugBreak();
        break;
    }
}
 
VOID DebugPrintf(LPCSTR pszFormat, ...)
{
    CHAR szOutput[1024];
    va_list va;
 
    va_start(va, pszFormat);
    wvsprintf(szOutput, pszFormat, va);
    OutputDebugString(szOutput);
    va_end(va);
}
 
#ifdef UNITTEST
int main(void)
{
    INT a, b, c;
    ASSERT(1 + 1 == 2);
    TRACE("OK");
    a = 1;
    b = 2;
    c = a + b;
    ASSERT(a + b == c);
    TRACE("a == %d, b == %d, c == %d", a, b, c);
    ASSERT(1 == 0); // Assertion Failure
    return 0;
}
#endif  // def UNITTEST

ASSERT(x); は、式xが真ならば無視され、偽であれば次のようなメッセージボックスを表示する。

TRACE(...); は、printfと同じ書式で出力内容をデバッガに出力する。 td32では、[View]-[Log]でデバッガへの出力内容を確認できる。

ソース: debug.zip


戻る

©片山博文MZ
katayama.hirofumi.mz@gmail.com

inserted by FC2 system