ゆとりーなの日記

日記的な事を書いて行くと思はれる

MSVCでのデバッグ小ネタ

メモリリークを調󠄁べる

_CrtSetDbgFlagを使󠄁とメモリリークが檢出できる。アプリ終󠄁了時にメモリの解放忘れがあると、デバッガにその情󠄁報を出力してくれる。

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

デバッグビルドでしか有效にならないのでmainやWinMainの先頭でそのまま呼ぶだけでよい(#ifdefとかで切る必要󠄁はない)。
ただこれで檢出できるリークはCランタイムによるメモリ確保(要󠄁はnewとかmallocとか)だけなので、COMでのRelease忘れなどは殘念ながら檢出できない。

std::coutのやうな使󠄁ひ勝󠄁手でデバッガに文󠄁字を出力する

OutputDebugStringはVisual Studioのデバッガに文󠄁字を出力できるのだがprintfのやうにフォーマットを指定して出力するといつた機󠄁能がない。std::coutのやうにお氣輕に數値などを出力できると便󠄁利なので、Boost.Iostreamsを使󠄁つてデバッガに文󠄁字を出力するストリームを作る。

#ifdef _DEBUG
class DebugOutSink : public boost::iostreams::sink {
 public:
  std::streamsize write(const char *s, std::streamsize n) {
    OutputDebugString(std::string(s, static_cast<std::string::size_type>(n)).c_str());
    return n;
  }
};

DebugOutSink debugSink;
boost::iostreams::stream<DebugOutSink> dout{debugSink};
#endif

boost::iostreams::sinkを繼承したクラスでwriteメンバ函數を實裝するだけでお手輕に出力ストリームを作成󠄁できる。wtiteには書き込󠄁むべき文󠄁字のポインタと文󠄁字數がくるのでそれを元にstd::stringで書き込󠄁むべき文󠄁字を一旦作つてからそれをOutputDebugStringを渡す(sがNULL終󠄁端かどうかやsにNULL文󠄁字を書くだけの餘分󠄁な領域を確保したポインタかどうかがよく分󠄁らないため)。
あとはstd::coutのやうなノリで使󠄁へるやうにグローバル變數としてストリームを定義しておけばデバッガに出力するストリームが使󠄁へるやうになる。ストリームを定義するには、作つたDebugOutSinkの變數をboost::iostreams::streamコンストラクタに渡す。

boost::iostreams::stream<DebugOutSink> dout;

でもコンパイルは通󠄁るのだがDebugOutSinkのコンストラクタが呼ばれないので明示的に外から渡す必要󠄁がある。

#ifdef _DEBUG
  dout << "デバッグ樂しい" << std::endl; 
#endif

のやうな風に使󠄁ふ事ができる。
因みにワイド文󠄁字列版はboost::iostreams::sinkの代はりにboost::iostreams::wsinkを繼承してcharをwchar_t、std::stringをstd::wstingに換へればあつさり作れたりする。

#ifdef _DEBUG
class DebugWOutSink : public boost::iostreams::wsink {
 public:
  std::streamsize write(const wchar_t *s, std::streamsize n) {
    OutputDebugString(std::wstring(s, static_cast<std::wstring::size_type>(n)).c_str());
    return n;
  }
};

DebugWOutSink debugWSink;
boost::iostreams::stream<DebugWOutSink> wdout{debugWSink};
#endif