結果だけでなく過程も見てください

日々の奮闘を綴る日記です。

可変引数を利用してVSのデバッグ出力ウィンドウやウィンドウボックス等でデバッグメッセージを出す方法

皆さんC/C++デバッグメッセージを出したいときはどうしているでしょうか?

コンソールプログラムの場合はprintfやcoutで済ましている人もいるのではないでしょうか。

ではコンソールプログラムからWin32などのコンソールがないプログラムにした場合どうしますか。
printfを使っている箇所を以下のようにファイル出力に書き換えますか。

FILE* fp = fopen( "log.txt", "a" );
if ( fp != NULL )
{
    fprintf( fp, "ID:%d Message:%s\n", id, msg );  // printfから置き換え
    fclose( fp );
}

また可変引数ではなくconst char*しか受け付けないログ出力関数の場合などは
printfを使っている箇所で以下のように書き換えますか。

char tmp[512];
sprintf( tmp, "ID:%d Message%s\n", id, msg );
OutputLog( tmp );  // printfから置き換え

このような変更による影響を最小限にするため、
可変引数の自作ログ関数を作っておき、その中でメッセージ出力した方が良いでしょう。

普段は必ず自作ログ関数を使用します。
自作ログ関数の中でprintfするなりファイル出力するなり必要に応じて変更します。
こうすることで出力先を変更するときでも、ログ出力部分は何も変えずに済みますよね。


以下に可変引数の自作ログ関数を紹介します。

OutputDebugStringでVisualStudioのデバッグ出力ウィンドウにメッセージを出力し、
MessageBox APIでダイアログボックスに出力を行います。
ダイアログボックスを出すかどうかは第一引数で決まります。

VisualStudioのデバッグ出力ウィンドウにはデバッグコンパイル時だけ出力するようにしています。

// Debug時のDEBUGPRINTマクロとDEBUGPRINTLNマクロ
#if _DEBUG

    inline void __cdecl DebugPrintf( bool bOutputMB, const char *fmt, ... )
    {
        char     tmp[1024];
        va_list  ap;

        va_start( ap, fmt );
        vsprintf( tmp, fmt, ap );

        // VisualStudioのデバッグウィンドウには必ず出力する
        OutputDebugString( tmp );

        if( bOutputMB )
        {
            // メッセージボックスはフラグがONにされたときだけ出力
            ::MessageBox( NULL, tmp, "DEBUG MESSAGE", MB_OK );
        }

        va_end( ap );
    }

    #define DEBUGPRINT DebugPrintf

    inline void __cdecl DebugPrintfln( bool bOutputMB, const char *fmt, ... )
    {
        char     tmp[1024];
        va_list  ap;

        va_start( ap, fmt );
        vsprintf( tmp, fmt, ap );
        ::strcat( tmp, "\n" );

        // VisualStudioのデバッグウィンドウには必ず出力する
        OutputDebugString( tmp );

        if( bOutputMB )
        {
            // メッセージボックスはフラグがONにされたときだけ出力
            ::MessageBox( NULL, tmp, "DEBUG MESSAGE", MB_OK );
        }

        va_end( ap );
    }

    #define DEBUGPRINTLN DebugPrintfln

#else

    inline void __cdecl DebugPrintfln( bool bOutputMB, const char *fmt, ... )
    {
        char  tmp[1024];

        if( bOutputMB )    // リリース時はメッセージボックスのみ出力
        {
            va_list ap;

            va_start( ap, fmt );

            vsprintf( tmp, fmt, ap );
            ::strcat( tmp, "\n" );

            ::MessageBox(NULL, tmp, "DEBUG MESSAGE", MB_OK);

            va_end( ap );
        }
    }

    // リリース時は何もしない
    #define DEBUGPRINT __noop
    #define DEBUGPRINTLN DebugPrintfln

#endif

使用例です。

DEBUGPRINTLN( true, "ID:%dのオブジェクトが生成された(Msg:%s)", id, msg );

おまけで、可変引数を利用してstringを作成する関数も載せておきます。

// stringを作り出す便利関数
inline string MAKESTRING( const char *fmt, ... )
{
    va_list ap;

    va_start( ap, fmt );

    char tmp[1024];
    vsprintf( tmp, fmt, ap );
    string tmp2 = tmp;

    va_end(ap);

    return tmp2;
}

簡単ですが、あったら便利という感じです。

プライバシーポリシー お問い合わせ