差をつけるデバッグ術! ~ 知られざるログ出力

突然質問です。



問題が発生したことを知るためには、どこにログを出力しますか?




テキストファイル?


イベントログ?


データベース? ・・・ う・・・ まぁ、いいかもしれません。



・・・



他にはありませんか?




実は、意外と知られていないですが、ログの出力にとても有効な場所があるんです




特に内部データ出力、内部動作のトレースログなど、データ量が多いものは、


テキストに落としては重い。


リアルタイムに見られない



という問題があります。




そういう時に、とても有効です。

リアルタイムに見られて、「軽い」 場所があるんです。




それはズバリ、デバッガです。





「え? だどさん、開発のときの話だったの?リリースしてからだと思ったよ」




いえいえ。



もちろん、開発時も使えますが、開発時の話だけではありません。



本番環境にリリースしてからも有効なんです。



Windows API には OutputDebugString という API があり、これを呼び出すとデバッガにトレースログを出力することが出来ます。



こんな型です。


void WINAPI OutputDebugString(
__in_opt LPCTSTR lpOutputString
);


OutputDebugString をプログラムから呼ぶと、デバッガがあるときだけ、デバッガがそれを捕らえて、トレースログを表示します。デバッガが無いときは何もしません。



デバッガというと、WinDbg、CDB、Visual Studio IDE などいろいろありますが、OutputDebugString からの出力を見るだけなら SDK ツールの DbMon や、DebugView などのツールを使えばログをみることが出来ます



ちなみに、.NET Framework では System.Diagnostics.Debug.Write 等が同様のことをします。




よくやるのは、開発者用のレジストリや構成ファイルに DebugLog 値を設定しておき、運用時に障害が発生したときだけそれを True にするとデバッグトレースが出力される、というようなことです。



DebugView の準備

デバッグトレースを表示するツールとして、今回は DebugView というツールを利用します。

マイクロソフトのサイトから DebugView をダウンロードします。

zip ファイルを展開して、任意の場所に格納してください。DbgView.exe が DebugView です。

テストプログラムの作成と試験

次に実際にテストプログラムを作成して、ログがどのように記録されるか確認してみましょう。

まずは、以下の内容を debugtest.cpp という名前で保存してください。


#include <windows.h>

int WINAPI WinMain ( 
	HINSTANCE hInstance, 
	HINSTANCE hPrevInstance, 
	LPSTR lpCmdLine, 
	int nCmdShow ) {

	for (int i=0; i<10; i++) {

		::Sleep( 1000 );
		::OutputDebugString( TEXT("Hello!\n") );

	}

	return 0;
}

ここでは 1 秒 Sleep で待って、OutputDebugString を呼び出す、という処理を for ループで10回行います。

メイクファイルは次のようになります。珍しいところは何もありません。


TARGETNAME=debugtest
OUTDIR=.\chk
LINK32=link.exe

ALL : "$(OUTDIR)\$(TARGETNAME).exe"


"$(OUTDIR)" :
    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"

# compile
CPP_PROJ=\
	/O1\
	/nologo\
	/W4\
	/Fo"$(OUTDIR)\\"\
	/Fd"$(OUTDIR)\\"\
	/c\
	/Zi\
	/DUNICODE\
	/D_UNICODE\

LINK32_FLAGS=\
	/nologo\
	/subsystem:windows\
	/pdb:"$(OUTDIR)\$(TARGETNAME).pdb"\
	/out:"$(OUTDIR)\$(TARGETNAME).exe"\
	/DEBUG
	
LINK32_OBJS= \
	"$(OUTDIR)\$(TARGETNAME).obj"
	

"$(OUTDIR)\$(TARGETNAME).exe" : "$(OUTDIR)" $(LINK32_OBJS)
    $(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS)


.cpp{$(OUTDIR)}.obj:
   $(CPP) $(CPP_PROJ) $<

このプログラムをビルドします。これでテストプログラムが完成です。

上記の DebugView を起動しつつ、ここで作った debugtest.exe を実行すると、以下のように DebugView にログが記録されることが確認できます。

ちゃんとログが見られたでしょうか?

この方法はリアルタイムのモニターツールとして、大変役に立ちますので、 あなたのプログラムにもデバッグトレース機能を埋め込んでみてください。


>> 私だどさんの、ウィンドウズプログラミング推薦書籍はこちら

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説