Visual Studioを使ってWIndowsプログラムのデバッグ中に、プログラムや変数の状態を表示したい・残したいと思う人や、なんでstderrが使えないんじゃああ!という人向けメモ。
C/C++でこれをするには、OutputDebugStringや_RPTNという関数が便利。他にもATLTRACE, AtlTraceという関数がある。いずれも、Visual Studioの出力ウィンドウにメッセージを残す。
- OutputDebugString
- _RPT0, _RPTN, _RPTW0, _RPTWN
- _RPTF0, _RPTFN, _RPTFW0, _RPTFWN
- _RPTT0, _RPTTN, _RPTTF0, _RPTTFN
- ATLTRACE
- AtlTrace
OutputDebugString
■宣言
void OutputDebugStringA(LPCSTR lpOutputString)
void OutputDebugStringW(LPCWSTR lpOutputString)
■説明
pOutputStringで指定した文字列を出力する。puts相当の単純な関数。ただし、Release版でも出力しちゃうので注意。下記の通り、OutputDebugStringとしても使用可。この場合、UNICODEを使うかどうかでマクロにより関数が自動選択される。
■使用例
OutputDebugString("Calculation thread started\n");
■出力結果
Calculation thread started
■MSDN
_RPT0, _RPTN, _RPTW0, _RPTWN
■宣言
_RPT0(int rptno, char const* msg)
_RPTN(int rptno, char const* msg, ...)
_RPTW0(int rptno, wchar_t const* msg)
_RPTWN(int rptno, wchar_t const* msg, ...)
■説明
_RPTN, _RPTWNはmsgに出力メッセージのフォーマットを指定でき、また可変長引数を取る。要するに、printfと同様の使い方ができ、変数値を出力したい時に便利。また、Release版では出力されなくなるのも良い。なお、出力したい文字列に%d等の書式指定構文が含まれない場合は、_RPT0や_RPTW0を使う必要がある。
rptnoには_CRT_WARNを通常指定する。デバッグ出力ウィンドウに出すだけでなく、ダイアログまで出したい場合は_CRT_ERRORまたは_CRT_ASSERTを指定する。どちらでも同じ。
Visual Studio 2012以前では_RPTN, _RPTWNを使用できない。代わりに_RPT1, _RPT2等を使用すること。
蛇足だが、例えば_RPT0はマクロで
#define _RPT0(rptno, msg) _RPTN(rptno, "%s", msg)
のような形で定義されている(わかりやすいようにちょっと改変)。
■使用例
_RPTN(_CRT_WARN, "deleting %Xh\n", org.m_Data[i]);
■実行結果
deleting 4E29748h
■MSDN
_RPTF0, _RPTFN, _RPTFW0, _RPTFWN
■宣言
_RPTF0(int rptno, char const* msg)
_RPTFN(int rptno, char const* msg, ...)
_RPTFW0(int rptno, wchar_t const* msg)
_RPTFWN(int rptno, wchar_t const* msg, ...)
■説明
こちらもprintfと同様の使い方ができる。また、Release版では出力されなくなる。上記_RPT0等と同様の注意が必要。_RPT0等との違いは、出力が発生したソースファイル名と行番号が出力に付加される点。実行結果参照。
Visual Studio 2012以前では_RPTFN, _RPTFWNを使用できない。代わりに_RPTF1, _RPTF2等を使用すること。
■使用例
_RPTFN(_CRT_WARN, "deleting %Xh\n", org.m_Data[i]);
■実行結果
c:\****\kanmusulistmakerdlg.cpp(838) : deleting 6D1AC88h
■MSDN
_RPTT0, _RPTTN, _RPTTF0, _RPTTFN
何故か存在しない。_RPT_WARNをいちいち書かなくてもよくしたものが以下にある。
ATLTRACE
■宣言
void ATLTRACE(LPCSTR pszFmt, ...)
■説明
pszFmtで指定した文字列を、その文字列で指定したフォーマットに従い出力する。printf相当。Debug版でだけ出力する。
■使用例
ATLTRACE("Swap!:%d\n", counter);
■出力例
c:\******\dragdroplistbox.cpp(95) : atlTraceGeneral - swap!5
デフォルトだとメッセージを発生させたファイル名と行番号も一緒に出力される。
Visual Studio2012以前を使っている場合は、MFC/ATL Trace Toolというものを使って出力内容を制御可能だが、ATLのデバッグ/トレース機能はVisual Studio2013から大きく変わってしまい、2013以降では上記ソフトが存在しない。2016年1月時点では設定変更不能のようだ。デバッグ情報のカテゴリが指定できる等、_RPTNよりも細かい出力が出来たはずだがソフト消滅により存在価値が無くなったようだ。
参考:ATL and MFC changes and fixes in Visual Studio 2013 | Visual C++ Team Blog
AtlTrace
■宣言
void AtlTrace(LPCSTR pszFormat, ...)
void AtlTrace(LPCWSTR pszFormat, ...)
■説明
ATLTRACEと同様だが、こちらはファイル名や行番号がそれぞれnullと-1になり、ちょっとすっきりする。でも、現時点では_RPTN系で充分である。
■使用例
AtlTrace("Num:%d data:%Xh\n", i, m_Data[i]);
■出力例
(null)(-1) : atlTraceGeneral - Num:11 data:4D198F0h