はじめに
アプリケーションを長時間動作させた際にハンドル数がいちじるしく増加していく場合、ハンドルリークが発生している可能性が疑われます。
オライリージャパン
売り上げランキング: 210,805
ハンドルリークは、アプリケーションが不要になったリソースを解放しないことが原因で発生します。
結果としてハンドルリソースのリークが発生し、最終的には制限に達して、そのアプリケーションや他のアプリケーション、またはシステム全般の動作が異常になったり、動作の診断が難しくなります。
この記事では、WinDbgを使ってハンドルリークを調査する方法をまとめました。
必要なもの
- WinDbg
- 以下のページからWindows 8.1 用 Windows ソフトウェア開発キットを入手します。
- https://msdn.microsoft.com/ja-JP/windows/desktop/bg162891
インストーラを起動し、Debugging Tools for Windowsをインストールしてください。
ハンドルリークするサンプルプログラム(HandleLeakApp.exe)
以下のプログラムを実験に使います。fopenしてfcloseしていないのでファイルハンドルが徐々に増えていきます。
#include "stdafx.h" #include "windows.h" #include <stdlib.h> #pragma warning(disable : 4996) int _tmain(int argc, _TCHAR* argv[]) { system("pause"); FILE *fp; char *filename = "c:\\sample.txt"; int i = 0; while (i < 10000) { // ファイルのオープン if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "%sのオープンに失敗しました(%d)\n", filename, GetLastError()); return 1; } // handle leak! //fclose(fp); printf("%d", i); Sleep(500); // 500msスリープ i++; } return 0; }
このプログラムを動作させると、タスクマネージャ上でハンドル数が増加していくのが分かります。
WinDbgを使ってハンドルリークを調査する
1.WinDbgを起動します。
2.Ctrl + Sでシンボルパスに以下を指定します。
srv*c:\websymbols*http://msdl.microsoft.com/download/symbols;
3.調査対象のアプリケーション(ここではHandleLeakApp.exe)を起動します。
4.F6キーからHandleLeakApp.exeにアタッチします。
5.!htrace -enableコマンドを実行します。
0:001> !htrace -enable
Handle tracing enabled.
Handle tracing information snapshot successfully taken.
6.!htrace -snapshotコマンドを実行します。
0:001> !htrace -snapshot
Handle tracing information snapshot successfully taken.
7.g コマンドを実行し、デバッガを走らせます。
8.HandleLeakApp.exeをしばらく動作させ、ハンドル数が増加していくことを確認します。
9.WinDbgをbreakさせます。
10.!htrace -diffコマンドを実行します。
スタックトレースが出力されています。
Displayed 0x5c stack traces for outstanding handles opened since the previous snapshot.
0x5c=10進数で92なので、snapshotを仕掛けてから92個のハンドルが開かれたことが分かります。
スタックが特定できると、ここから原因を調べていくことができるようになると思います。