1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WinDbg+生成AIでメモリusageを解析する

1
Last updated at Posted at 2026-02-24

将来的にはAIエージェント(Windows Copilot)で「メモリ使用量が大きいexeが検知されたので自動解析して原因はここ、オープンソースのexeなので修正のプルリク送りますか?」くらいの可能性も考えてしまいますが、現時点でも生成AIの力を借りてのデバッグめっちゃ良い感じです(バイナリを数秒で解析できるという)

  • Win11
  • 試しにpulsar.exeを解析 (OSSのエディタ)

プロンプト

process explorerで取得したプロセスのmini dumpの解析方法

生成AI回答

Process Explorerで取得したミニダンプ(.dmpファイル)は、特定の瞬間のメモリ状態を切り取ったスナップショットです。これを解析することで、アプリがなぜフリーズしたのか、あるいはクラッシュしたのかを特定できます。

最も一般的で強力な解析ツールは、Microsoftが提供している WinDbg (Windows Debugger) です。


1. 事前準備

解析を始める前に、以下のツールを揃えておきましょう。

  • WinDbg (Preview版がおすすめ): Microsoft Storeから無料で入手できます。
  • シンボルファイル (PDB): プログラムのコードとメモリ上のアドレスを紐付けるための辞書のようなものです。Microsoft製品(Windows自体など)のシンボルは、後述の設定で自動取得できます。

2. WinDbg での解析手順

ステップ1:ダンプファイルを開く

  1. WinDbg を起動します。
  2. File > Open dump file を選択し、Process Explorerで保存した .dmp ファイルを選択します。

ステップ2:シンボルパスの設定

デバッグを意味のあるものにするために、Microsoftのシンボルサーバーを設定します。
コマンドプロンプト(下部の入力欄)に以下を入力し、Enterを押してください。

.symfix+ c:\symbols
.reload

c:\symbols はキャッシュ先フォルダです。任意の場所で構いません。

ステップ3:自動解析コマンド (!analyze -v)

これが最も重要なステップです。WinDbgには問題を自動診断する機能があります。
以下のコマンドを入力してください。

!analyze -v

ステップ4:出力結果の読み方

解析が終わると、膨大なテキストが表示されます。特に以下の項目に注目してください。

  • FAULTING_IP: 障害が発生した命令ポインタ(どこで止まったか)。
  • STACK_TEXT: 関数の呼び出し履歴。下から上へ読みます。自分の作成したアプリであれば、どの関数で問題が起きたか一目瞭然です。
  • EXCEPTION_CODE: 0xc0000005 (メモリアクセス違反) など、エラーの種類を示します。

3. その他の便利なコマンド

特定の状態を深掘りしたいときに使ってみてください。

コマンド 説明
~*k すべてのスレッドのコールスタックを表示(フリーズ調査に便利)
lm ロードされているモジュール(DLL等)の一覧を表示
!address -summary メモリの使用状況の概要を表示

注意点

Process Explorerで取得する際、**「Create Full Dump」ではなく「Create Mini Dump」**を選んだ場合、含まれる情報が制限されます(ヒープメモリの内容が含まれないなど)。詳細な変数の中身まで追いたい場合は、次回から Full Dump を取得することをお勧めします。

解析中にエラーが出たり、特定の関数名が Unknown になったりして困っていませんか? もしよろしければ、!analyze -v の結果の一部(個人情報や機密情報を含まない範囲)をこちらに貼っていただければ、一緒に内容を確認しますよ。

操作

  • 試しにprocess explorerでmini dump取ってみたけど、今回試したいのはメモリusageの解析なので、フルダンプで取り直した (404MB)
  • WinDbgをダウンロード & インストール & 実行
  • command (中央ペイン) で以下を実行
.symfix+ c:\symbols
.reload
.sympath
  • この状態で !analyze -v してみるが、no symbol出力
  • 生成AI曰く、ローカルのシンボルファイルが足りてないのでMicrosoftのサーバからダウンロードが必要ということ
  • 以下を実行
.sympath srv*c:\symbols*http://msdl.microsoft.com/download/symbols
.reload /f
  • 上記が正常に通ると、実行時にシンボルのダウンロードが走る (ゲージが表示される)
  • 以下各出力

メモリ統計

0:000> !heap -s


************************************************************************************************************************
                                              NT HEAP STATS BELOW
************************************************************************************************************************
LFH Key                   : 0xa64420e0671b840b
Termination on corruption : ENABLED
          Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                            (k)     (k)    (k)     (k) length      blocks cont. heap 
-------------------------------------------------------------------------------------
00000282024a0000 00000002    8568   6452   8176    852   191     4    0     2c   LFH
    External fragmentation  13 % (191 free blocks)
0000028202340000 00000002     456     44     64      8     2     1    0      0   LFH
0000028202440000 00008000      64      4     64      2     1     1    0      0      
0000028202790000 00001002    1472    152   1080     21     9     2    0      0   LFH
0000028202ef0000 00001002      60      8     60      5     1     1    0      0      
0000028203380000 00001002      60      8     60      5     1     1    0      0      
0000028203370000 00001002     452     44     60      1     1     1    0      0   LFH
000002820a6d0000 00001002     452     44     60      8    10     1    0      0   LFH
-------------------------------------------------------------------------------------

アドレスサマリ

0:000> !address -summary

                                     
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
SYMSRV2: [kernelbase.pdb] Uri c:\symbols\kernelbase.pdb\A90E5D05D0B1888A19154D2C8EA9C6871\file.ptr
SYMSRV2: [index2.txt] GET from host msdl.microsoft.com
SYMSRV2: [index2.txt] Downloaded 0 percentSYMSRV2: Header reply: http/1.1 404 not found

SYMSRV2: Header reply: x-cache: tcp_hit

SYMSRV2: Header reply: x-powered-by: asp.net

SYMSRV2: Header reply: strict-transport-security: includesubdomains

SYMSRV2: Header reply: x-msedge-ref: ref a: f48605f5d18f4f56a62f24d4bd79ef45 ref b: tyaedge0706 ref c: 2026-02-24t21:27:10z

SYMSRV2: Header reply: date: tue, 24 feb 2026 21:27:10 gmt

SYMSRV2: Header reply: content-length: 0

SYMSRV2: Header reply: 

0 percent
SYMSRV2: [index2.txt] HTTP 404 (request #0)
SYMSRV2: [index2.txt] Checking response kind: ResponseOther { symbol_agent_status: None }
SYMSRV2: [index2.txt] http_download_from_symbol_server failed. Error: HTTP 404: File not found. Host: msdl.microsoft.com
SYMSRV2: http_download_from_symbol_server failed. Error: HTTP 404: File not found. Host: msdl.microsoft.com
SYMSRV2: [kernelbase.pdb] Uri from host msdl.microsoft.com
SYMSRV2: [kernelbase.pdb] GET from host msdl.microsoft.com
SYMSRV2: [kernelbase.pdb] Downloaded 0 percentSYMSRV2: Header reply: http/1.1 302 found

SYMSRV2: Header reply: location: https://vsblobprodscussu5shard66.blob.core.windows.net/b-4712e0edc5a240eabf23330d7df68e77/56253d1a90ff31afaa2d3c3db4ba0ff89e692e53789b2ebff93102f7e6a4393400.blob?sv=2019-07-07&sr=b&sig=ml9sbbcjzja240otd%2fkj8fiyzkvtkzqkyw4h6t3lz3k%3d&skoid=4866d8d7-57cb-4216-997d-bade18bdbe68&sktid=33e01921-4d64-4f8c-a055-5bdaffd5e33d&skt=2026-02-24t19%3a06%3a02z&ske=2026-02-26t20%3a06%3a02z&sks=b&skv=2019-07-07&se=2026-02-25t21%3a20%3a11z&sp=r&rscl=x-e2eid-51685133-0c974037-bdcd05a2-c79ecddd-session-089ea19f-260340c6-9bcda055-1aa17033

SYMSRV2: Header reply: x-cache: tcp_miss

SYMSRV2: Header reply: x-powered-by: asp.net

SYMSRV2: Header reply: strict-transport-security: includesubdomains

SYMSRV2: Header reply: x-msedge-ref: ref a: e1547683c16a4cbc99103b3cccd998d4 ref b: tyaedge0805 ref c: 2026-02-24t21:27:10z

SYMSRV2: Header reply: date: tue, 24 feb 2026 21:27:09 gmt

SYMSRV2: Header reply: content-length: 0

SYMSRV2: Header reply: 

0 percentSYMSRV2: Header reply: http/1.1 206 partial content

SYMSRV2: Header reply: content-length: 8000000

SYMSRV2: Header reply: content-type: application/octet-stream

SYMSRV2: Header reply: content-language: x-e2eid-51685133-0c974037-bdcd05a2-c79ecddd-session-089ea19f-260340c6-9bcda055-1aa17033

SYMSRV2: Header reply: content-range: bytes 0-7999999/12267520


SYMSRV2: [kernelbase.pdb] Making 2 GET requests total.
SYMSRV2: [kernelbase.pdb] Downloaded  99 percent, 12194304/12267520
SYMSRV2: [kernelbase.pdb] Checking response kind: Response206 { file_size_from_content_range: Some(12267520) }
SYMSRV2: [kernelbase.pdb] Downloaded successfully, took 5439 ms for 12267520 bytes.
DBGHELP: KERNELBASE - public symbols  
        c:\symbols\kernelbase.pdb\A90E5D05D0B1888A19154D2C8EA9C6871\kernelbase.pdb
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...

--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free                                    192     7df5`d8b0d000 ( 125.960 TB)           98.41%
<unknown>                              1551      20a`095f2000 (   2.039 TB)  99.98%    1.59%
Image                                   629        0`0ec9b000 ( 236.605 MB)   0.01%    0.00%
Stack                                    87        0`0e800000 ( 232.000 MB)   0.01%    0.00%
Heap                                     13        0`0085e000 (   8.367 MB)   0.00%    0.00%
Other                                    10        0`001bd000 (   1.738 MB)   0.00%    0.00%
TEB                                      29        0`0003a000 ( 232.000 kB)   0.00%    0.00%
PEB                                       1        0`00001000 (   4.000 kB)   0.00%    0.00%

--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_MAPPED                              210      200`06403000 (   2.000 TB)  98.06%    1.56%
MEM_PRIVATE                            1315        a`12665000 (  40.287 GB)   1.93%    0.03%
MEM_IMAGE                               795        0`0ea7b000 ( 234.480 MB)   0.01%    0.00%

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                192     7df5`d8b0d000 ( 125.960 TB)           98.41%
MEM_RESERVE                             720      20a`08a6c000 (   2.039 TB)  99.98%    1.59%
MEM_COMMIT                             1600        0`1ea77000 ( 490.465 MB)   0.02%    0.00%

--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
PAGE_EXECUTE_READ                       199        0`0a6a9000 ( 166.660 MB)   0.01%    0.00%
PAGE_READONLY                           415        0`08e3d000 ( 142.238 MB)   0.01%    0.00%
PAGE_READWRITE                          818        0`05a78000 (  90.469 MB)   0.00%    0.00%
PAGE_NOACCESS                            62        0`053d2000 (  83.820 MB)   0.00%    0.00%
PAGE_WRITECOPY                           70        0`004f2000 (   4.945 MB)   0.00%    0.00%
PAGE_EXECUTE_READ | PAGE_GUARD            3        0`001f4000 (   1.953 MB)   0.00%    0.00%
PAGE_READWRITE | PAGE_GUARD              29        0`00057000 ( 348.000 kB)   0.00%    0.00%
PAGE_EXECUTE_READWRITE                    4        0`0000a000 (  40.000 kB)   0.00%    0.00%

--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
Free                                    5f0`00000000     376e`a2100000 (  55.432 TB)
<unknown>                              7dff`3734e000      19d`ebd63000 (   1.617 TB)
Image                                  7ff6`601b1000        0`066b0000 ( 102.688 MB)
Stack                                    d3`62e00000        0`007fc000 (   7.984 MB)
Heap                                    282`05e54000        0`001cb000 (   1.793 MB)
Other                                   282`03390000        0`00181000 (   1.504 MB)
TEB                                      d3`5ac5c000        0`00002000 (   8.000 kB)
PEB                                      d3`5ad8f000        0`00001000 (   4.000 kB)

アドレス出力

0:000> !address

                                     
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...

        BaseAddress      EndAddress+1        RegionSize     Type       State                 Protect             Usage
--------------------------------------------------------------------------------------------------------------------------
+        0`00000000        0`7ffe0000        0`7ffe0000             MEM_FREE    PAGE_NOACCESS                      Free       
+        0`7ffe0000        0`7ffe1000        0`00001000 MEM_PRIVATE MEM_COMMIT  PAGE_READONLY                      Other      [User Shared Data]
+        0`7ffe1000        0`7ffec000        0`0000b000             MEM_FREE    PAGE_NOACCESS                      Free       
+        0`7ffec000        0`7ffed000        0`00001000 MEM_PRIVATE MEM_COMMIT  PAGE_READONLY                      <unknown>  [..........Mp....]
+        0`7ffed000       d3`5ac00000       d2`dac13000             MEM_FREE    PAGE_NOACCESS                      Free       
+       d3`5ac00000       d3`5ac5c000        0`0005c000 MEM_PRIVATE MEM_RESERVE                                    <unknown>  
        d3`5ac5c000       d3`5ac5e000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~27; 1c78.71d8]
        d3`5ac5e000       d3`5ac60000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~28; 1c78.8600]
        d3`5ac60000       d3`5ad8f000        0`0012f000 MEM_PRIVATE MEM_RESERVE                                    <unknown>  
        d3`5ad8f000       d3`5ad90000        0`00001000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     PEB        [1c78]
        d3`5ad90000       d3`5ad92000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~0; 1c78.490c]
        d3`5ad92000       d3`5ad98000        0`00006000 MEM_PRIVATE MEM_RESERVE                                    <unknown>  
        d3`5ad98000       d3`5ad9a000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~1; 1c78.5df8]
        d3`5ad9a000       d3`5ad9c000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~2; 1c78.1794]
        d3`5ad9c000       d3`5ad9e000        0`00002000 MEM_PRIVATE MEM_RESERVE                                    <unknown>  
        d3`5ad9e000       d3`5ada0000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~3; 1c78.6370]
        d3`5ada0000       d3`5ada2000        0`00002000 MEM_PRIVATE MEM_RESERVE                                    <unknown>  
        d3`5ada2000       d3`5ada4000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~4; 1c78.7c5c]
        d3`5ada4000       d3`5ada6000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~5; 1c78.31f0]
        d3`5ada6000       d3`5ada8000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~6; 1c78.3d34]
        d3`5ada8000       d3`5adaa000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~7; 1c78.7b24]
        d3`5adaa000       d3`5adac000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~8; 1c78.67d0]
        d3`5adac000       d3`5adae000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~9; 1c78.2df8]
        d3`5adae000       d3`5adb0000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~10; 1c78.5f78]
        d3`5adb0000       d3`5adb2000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~11; 1c78.1f10]
        d3`5adb2000       d3`5adb4000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~12; 1c78.6b9c]
        d3`5adb4000       d3`5adb6000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~13; 1c78.6d2c]
        d3`5adb6000       d3`5adb8000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~14; 1c78.7904]
        d3`5adb8000       d3`5adba000        0`00002000 MEM_PRIVATE MEM_COMMIT  PAGE_READWRITE                     TEB        [~15; 1c78.41c4]

... 3000行くらいある ...

プロンプト

!address 結果を貼り付け

生成AI回答

提供いただいたファイル(pulsar.exe-fulldump-heap)に含まれる !address の詳細な出力結果に基づき、メモリ使用量が正常かどうかを解析しました。

結論から申し上げますと、**「現時点でのメモリ使用量は概ね正常の範囲内ですが、スレッド数とそれに伴うスタックメモリがやや多い」**という状態です。

以下に詳細な分析結果をまとめます。


1. メモリ使用の内訳分析

コミット済みメモリ(実際に消費されているメモリ)の主な要因は以下の通りです。

スレッドスタック (Stack): 約 232 MB

分析: ダンプ内には少なくとも 29個以上のスレッド(~0から~28まで確認)が存在します 。各スレッドは約1MBのスタック領域を予約しており、合計で230MB以上がこの用途に割り当てられています。

  • 判断: アプリケーションの規模によりますが、もしシンプルなツールであればスレッド数が多めです。不要なスレッドが終了せずに残っている(スレッドリーク)可能性を検討する余地があります。

動的メモリ (Heap): 約 8.3 MB

  • 分析: メインヒープ(Handle: 00000282024a0000)などで消費されているメモリは非常に少なく、10MB以下に抑えられています。

  • 判断: ヒープメモリに関しては極めて健全であり、現時点でのメモリリーク(オブジェクトの解放漏れ)の疑いは低いです。

  • 実行ファイル・DLL (Image): 約 236 MB

  • 分析: アプリ本体や ntdll.dll などのシステムライブラリが占める領域です。

  • 判断: これはプログラムの実行に必須の領域であり、異常ではありません。


2. 懸念点:スレッドスタックの占有率

全体のコミット量(約490MB)のうち、約半分が「スレッドのスタック」で占められています。

PAGE_GUARD の存在: 多くのスタック領域で PAGE_GUARD(スタックオーバーフロー防止用の保護ページ)が正しく設定されており、メモリ管理自体は正常に行われています 。

スレッドの役割: TEB(Thread Environment Block)の情報を確認すると、短時間に多くのスレッドが生成されたような形跡があります 。


3. 次に確認すべきこと

メモリ使用量が「正常か」をさらに確定させるために、以下のコマンドでスレッドの状態を確認することをお勧めします。

  1. スレッドが何をしているか確認
~*kb

これで全スレッドのバックトレースを表示します。もし「似たようなスタック(処理待ちなど)」を持つスレッドが大量にある場合、スレッドが適切に再利用・破棄されていない可能性があります。
2. 特定の巨大なメモリ領域(Unknown)の確認

!address の出力で、用途が <unknown> かつ MEM_COMMIT になっている領域(例:281'c2ca0000 付近など )がいくつかあります。これらが何であるか、以下のコマンドで中身を数行覗いてみてください。

db 281`c2ca0000 L40

まとめ:
ヒープは綺麗ですが、「スレッドの多さ」がメモリ消費の主因となっています。意図的に多くの並列処理を行っていないのであれば、スレッドの生成・破棄サイクルを見直すことで、メモリ使用量をさらに半分程度まで削減できる可能性があります。

操作

  • db 281`c2ca0000 L40を実行

プロンプト

出力を生成AIに貼り付け

生成AI回答

実行した db コマンドの結果から、このメモリ領域(00000281'c2ca0000)の正体と、メモリ使用状況が正常かどうかの判断材料が見えてきました。

1. メモリの内容解析

先頭にある 64 74 72 52 というデータに注目してください。これを ASCII 文字に直すと dtrR となります。

これは、Google の「Abseil (absl)」ライブラリ や、それを利用するフレームワーク(gRPC や特定の C++ ライブラリ)が内部的に使用するミューテックス(排他制御)や同期オブジェクトに関連するシグネチャ(マジックナンバー)である可能性が高いです。

  • データ構造の特徴: その後に続く 00 00 00 00 や多くのアドレス値、およびゼロ埋めされた領域は、プログラムが動的に管理している「管理テーブル」や「オブジェクトのプール」の一部であることを示唆しています。

2. メモリ使用量は正常か?

この 40 バイトの断片と、先ほどの !address の結果を照らし合わせると、以下のことが言えます。

  • 断片化の可能性: ヒープ(Heap)の統計値が約 8MB と非常に小さかったのに対し、この領域は MEM_PRIVATE(個別に直接確保された領域)として存在しています。
  • 判断:
  • 正常なケース: Pulsar.exe がネットワーク通信(gRPCなど)や、高度な並列計算を行っている場合、ライブラリ側が効率化のためにあらかじめ大きなメモリ空間を確保(予約)しておくことがあります。この dtrR 領域が数個程度であれば、全く問題ありません。
  • 異常なケース: もし !address のリストの中に、この dtrR で始まるような数 MB 単位の MEM_COMMIT 領域が大量に(何十個も)並んでいる場合は、同期オブジェクトの破棄漏れ(リソースリーク)を疑う必要があります。

3. 次の決定的な調査

この「謎のメモリ確保」が Pulsar.exe のどこから来ているのかを特定するために、以下のコマンドを試してください。

!address 281`c2ca0000

これによって、この特定の 40 バイトが含まれる「大きなメモリの塊」が、全体でどれくらいのサイズ(RegionSize)なのかがわかります。

  • RegionSize が 64KB や 1MB 単位の場合: 単なるスレッドごとの管理データであり、正常です。
  • RegionSize が非常に小さいものが無数にある場合: メモリ管理の効率が落ちている(断片化している)可能性があります。

まとめ

現在の 490MB の消費の内訳は、「巨大なデータの蓄積(リーク)」ではなく、「大量のスレッドスタック」と「ライブラリが確保した管理領域」の合算によるものです。

もし Pulsar.exe が起動から時間が経つにつれて 490MB から 1GB, 2GB と増え続けていないのであれば、この状態は「このアプリの設計上の仕様(スレッドを多く使う設計)」であり、故障やバグではないと判断して良いでしょう。

追記

本記事はprocess explorerでプロセスのフルダンプを取得 & WinDbgでメモリを解析
でやりましたが、やりたいのはプロセス内でどのオブジェクトがメモリを食っているか、で、それを実現するのは以下の方が簡単でした

  • タスクマネージャでプロセスを右クリックでダンプ取得 & dotnet-dump.exe analyze xxxx.DMP & dumpheap -statでオブジェクトごとのメモリ使用量をランキング
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?