将来的には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:ダンプファイルを開く
- WinDbg を起動します。
-
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. 次に確認すべきこと
メモリ使用量が「正常か」をさらに確定させるために、以下のコマンドでスレッドの状態を確認することをお勧めします。
- スレッドが何をしているか確認
~*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でオブジェクトごとのメモリ使用量をランキング