LoginSignup
14
15

More than 5 years have passed since last update.

Visual C++ で作る printf 風デバッグのためのマクロ

Last updated at Posted at 2013-06-25

「引数で与えられた書式+引数を、ソースファイル名と行番号付きで表示するマクロ」の作り方4種。

printf といっても出力先はデバッガの出力ウィンドウです
_CrtDbgReport 使ってるので _CrtSetReportMode/_CrtSetReportFile で出力先を標準出力とかに変えられます)。

その1. __noop を使う

関数オブジェクトのコンストラクタで __FILE____LINE__ を受け取り、括弧演算子で printf な書式と引数を受け付けます。

リリースビルドでは __noopTRACE_F マクロの中身が実行されないようにします。

#ifdef _DEBUG

#include <crtdbg.h>
#define TRACE_F debug_trace_format(__FILE__, __LINE__)

    class debug_trace_format
    {
    private:
        const char* _file;
        long _line;

    public:
        debug_trace_format(const char* file, long line) : _file(file), _line(line) {}

        void operator ()(const char *fmt, ...)
        {
            va_list arg;
            va_start(arg, fmt);
            int size = vsnprintf(NULL, 0, fmt, arg);
            std::unique_ptr<char[]> buf(new char[size + 1]);
            vsnprintf(buf.get(), size + 1, fmt, arg);
            _CrtDbgReport(_CRT_WARN, _file, _line, NULL, "%s", buf.get());
            va_end(arg);
        }
    };

#else
#define TRACE_F __noop
#endif

int main()
{
    //_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    //_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
    TRACE_F("%s: %d\n", "errcode", 1234);
    return 0;
}

その2. __VA_ARGS__ を使う

いつからか Visual C++ で __VA_ARGS__ が使えるようになっていました。

#ifdef _DEBUG
#include <crtdbg.h>
#define TRACE_F(fmt, ...) _CrtDbgReport(_CRT_WARN, __FILE__, __LINE__, NULL, fmt, __VA_ARGS__);
#else
#define TRACE_F(fmt, ...)
#endif

int main()
{
    //_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    //_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
    TRACE_F("%s: %d\n", "errcode", 1234);
    return 0;
}

楽ちんです。

その3. stringstream を使う

可変個引数が気持ち悪い人のために stringstream を使う版。

#include <sstream>

#ifdef _DEBUG

#include <crtdbg.h>
#define TRACE_F(expr) _CrtDbgReport(_CRT_WARN, __FILE__, __LINE__, NULL, "%s", \
    static_cast<::std::ostringstream&>(::std::ostringstream() << expr).str().c_str() )

#else
#define TRACE_F(expr)
#endif

int main()
{
    //_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    //_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
    TRACE_F("errcode: " <<  1234 << std::endl);
    return 0;
}

その4. boost/format を使う

boost が使えるなら boost/format で。

#include <boost/format.hpp>

#ifdef _DEBUG

#include <crtdbg.h>
#define TRACE_F(fmt, expr) _CrtDbgReport(_CRT_WARN, __FILE__, __LINE__, NULL, "%s", \
    (::boost::format(fmt) % expr).str().c_str() )

#else
#define TRACE_F(fmt, expr)
#endif

int main()
{
    //_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
    //_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
    TRACE_F("%s: %d\n", "errcode" % 1234);
    return 0;
}

その?. ATLTRACE を使う

ファイル名と行番号を表示させる方法がわからなかったので使っていない。

14
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
15