PoolMon を使用してカーネル モード メモリ リークを検出する

カーネル モード メモリ リークが疑われる場合は、PoolMon ツールを使用して、どのプール タグがリークに関連しているかを特定できます。

PoolMon (Poolmon.exe) は、プール タグ名別にプール メモリ使用量を監視するツールです。 このツールは、Windows Driver Kit (WDK) に含まれています。 詳細については、「PoolMon」を参照してください。

GFlags プールの設定

Special Pool など、一部の GFlags 設定は、メモリ プールの使用方法に影響します。 詳細については、「GFlags」と「Special Pool の構成」を参照してください。

PoolMon を使用する

PoolMon ヘッダーには、ページ プールと非ページ プールの合計バイト数が表示されます。 列には、プール タグごとのプール使用量が表示されます。 表示は数秒ごとに自動的に更新されます。 次に例を示します。

Memory: 16224K Avail: 4564K PageFlts: 31 InRam Krnl: 684K P: 680K
Commit: 24140K Limit: 24952K Peak: 24932K Pool N: 744K P: 2180K

## Tag   Type  Allocs       Frees        Diff    Bytes       Per Alloc


CM    Paged   1283  ( 0)  1002  ( 0)   281  1377312   ( 0)  4901
Strg  Paged  10385 ( 10)  6658  ( 4)  3727   317952 ( 512)    85
Fat   Paged   6662  ( 8)  4971  ( 6)  1691   174560 ( 128)   103
MmSt  Paged    614  ( 0)   441  ( 0)   173    83456   ( 0)   482 

PoolMon には、さまざまな基準に従って出力を並べ替えるコマンド キーがあります。 データを並べ替えるには、各コマンドに関連付けられた文字を選択します。 各コマンドが機能するまでに数秒かかります。

並べ替えコマンドには次のものが含まれます。

コマンド キー 操作
P 表示されるタグを非ページ プール バイト、ページ プール バイト、またはその両方に制限します。 P を繰り返し押すと、これらのオプションがこの順に切り替わります。
B タグを最大バイト使用量に基づいて並べ替えます。
M タグを最大バイト割り当て量に基づいて並べ替えます。
T タグをタグ名のアルファベット順に並べ替えます。
E ページ プールの合計と非ページ プールの合計が下部に表示されるようにします。
A タグを割り当てサイズに基づいて並べ替えます。
F タグを解放操作の数に基づいて並べ替えます。
S タグを割り当てと解放の差に基づいて並べ替えます。
Q PoolMon を終了します。

PoolMon でドライバー名を表示する

PoolMon /g パラメーターを使用すると、各プール タグを割り当てた Windows コンポーネントと一般的に使用されるドライバーの名前を表示できます。 特定のタグの割り当てに問題が見つかった場合、この機能は問題のコンポーネントやドライバーを特定するのに役立ちます。

コンポーネントとドライバーは、表示の右端の列である Mapped_Driver 列に一覧表示されます。 Mapped_Driver 列のデータは、WDK と共にインストールされる pooltag.txt ファイルから取得されます。

次のコマンドは、/g パラメーターを使用して Mapped_Driver 列を追加する方法を示しています。

poolmon /g "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\triage\pooltag.txt"

特定のプールを表示する

/i パラメーターを使用して、特定の文字列 (Hid など) で始まるプール タグを表示します。

poolmon /iHid? /g "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\triage\pooltag.txt"

 Memory:33473120K Avail:20055132K  PageFlts:     5   InRam Krnl:10444K P:1843072K
 Commit:15035764K Limit:67027552K Peak:16677444K            Pool N:1023400K P:1955448K
 System pool information
 Tag  Type     Allocs            Frees            Diff       Bytes                 Per Alloc Mapped_Driver

 HidC Paged      1667 (   0)      1659 (   0)        8         896 (          0)         112 [hidclass.sys - HID Class d 
 HidC Nonp      17375 (   0)     17256 (   0)      119       19808 (          0)         166 [hidclass.sys - HID Class d 
 HidP Nonp       1014 (   0)       998 (   0)       16        6704 (          0)         419 [hidparse.sys - HID Parser]

PoolMon ユーティリティを使用してメモリ リークを検出する

PoolMon ユーティリティを使用してメモリ リークを検出する方法の 1 つを次に示します。

  1. PoolMon を起動します。

  2. 非ページ プールでリークが発生していると判断した場合は、P を 1 回選択します。 ページ プールでリークが発生していると判断した場合は、P を 2 回選択します。 わからない場合は、両方の種類のプールが含まれるように、P を選択します。

  3. B を選択すると、最大バイト使用量に基づいて表示が並べ替えられます。

  4. テストを開始します。 スクリーンショットを撮って保存するなどして、画面の出力をコピーします。

  5. 30 分ごとに新しいスクリーンショットを撮ります。 スクリーンショットを比較して、どのタグのバイト数が増加しているかを特定します。

  6. テストを停止し、数時間待ちます。 この間に、タグがどれだけ解放されたかを特定します。

通常、アプリケーションが安定して動作し始めると、メモリの割り当てとメモリの解放を同じ速度で行います。 メモリを解放するよりも早くメモリを割り当てると、時間の経過とともにメモリの使用量が増えます。 これは多くの場合、メモリ リークを示しています。

リークに対処する

どのプール タグがリークに関連しているかを特定したら、リークについて知る必要がある情報はほぼ揃っています。 リークの原因となっている割り当てルーチンを特定する必要がある場合は、「カーネル デバッガーを使用したカーネル モード メモリ リークの検出」を参照してください。