web-dev-qa-db-ja.com

Windowsクラッシュダンプファイルの詳細なメモリ使用量分析?

お客様からネイティブ(完全)クラッシュダンプファイルを受け取りました。 Visual Studio(2005)デバッガーで開くと、最大10MBのブロックを割り当てようとしたrealloc呼び出しが原因でクラッシュが発生したことがわかります。ダンプファイルは異常に大きかった(1.5GB-通常は500MB程度)。

したがって、プロセスのメモリを完全に使い果たしたか、少なくともreallocが失敗するのに十分なほど大幅にフラグメント化した、メモリ「リーク」または暴走した割り当てがあると結論付けます。 (このreallocは、ロギングバッファーを割り当てた操作用であり、ここで失敗したことは驚くことではありません。一度に10MBは、非常に大きなかなり変更できないバッファーとは別に、より大きな割り当ての1つになるためです。問題それ自体は、この特定の割り当てとは関係がない可能性があります。)

編集:以下のLex Liとコメントを交換した後、追加する必要があります:これは再現できません私たち(現時点)。これは、暴走したメモリ消費を明確に示す1つのcustomerダンプです。

主な質問:

これでダンプファイルができましたが、過剰なメモリ使用量の原因を特定するにはどうすればよいですか?

これまでに行ったこと:

DebugDiagツール を使用してダンプファイル(いわゆるメモリ圧力アナライザー)を分析しました。これが得られたものです。

Report for DumpFM...dmp

Virtual Memory Summary
----------------------
Size of largest free VM block   62,23 MBytes 
Free memory fragmentation       81,30% 
Free Memory                     332,87 MBytes   (16,25% of Total Memory) 
Reserved Memory                 0 Bytes   (0,00% of Total Memory) 
Committed Memory                1,67 GBytes   (83,75% of Total Memory) 
Total Memory                    2,00 GBytes 
Largest free block at           0x00000000`04bc4000 

Loaded Module Summary
---------------------
Number of Modules       114 Modules 
Total reserved memory   0 Bytes 
Total committed memory  3,33 MBytes 

Thread Summary
--------------
Number of Threads       56 Thread(s) 
Total reserved memory   0 Bytes 
Total committed memory  652,00 KBytes 

これは、ちょっとしたコンテキストを得るためだけのものでした。私が信じているより興味深いものは次のとおりです。

Heap Summary
------------
Number of heaps         26 Heaps 
Total reserved memory   1,64 GBytes 
Total committed memory  1,61 GBytes 

Top 10 heaps by reserved memory
-------------------------------
0x01040000           1,55 GBytes        
0x00150000           64,06 MBytes        
0x010d0000           15,31 MBytes        
...

Top 10 heaps by committed memory
--------------------------------                              
0x01040000       1,54 GBytes 
0x00150000       55,17 MBytes 
0x010d0000       6,25 MBytes  
...            

さて、ヒープを見て0x01040000(1.5 GB)表示:

Heap 5 - 0x01040000 
-------------------
Heap Name          msvcr80!_crtheap 
Heap Description   This heap is used by msvcr80 
Reserved memory      1,55 GBytes 
Committed memory     1,54 GBytes (99,46% of reserved)  
Uncommitted memory   8,61 MBytes (0,54% of reserved)  
Number of heap segments             39 segments 
Number of uncommitted ranges        41 range(s) 
Size of largest uncommitted range   8,33 MBytes 
Calculated heap fragmentation       3,27% 

Segment Information
-------------------
Base Address | Reserved Size   | Committed Size  | Uncommitted Size | Number of uncommitted ranges | Largest uncommitted block | Calculated heap fragmentation 
0x01040640        64,00 KBytes      64,00 KBytes   0 Bytes            0                              0 Bytes                     0,00% 
0x01350000     1.024,00 KBytes   1.024,00 KBytes   0 Bytes            0                              0 Bytes                     0,00% 
0x02850000     2,00 MBytes       2,00 MBytes       0 Bytes            0                              0 Bytes                     0,00% 
...

とにかくこのセグメント情報は何ですか?

リストされている割り当てを見てください:

Top 5 allocations by size
-------------------------
Allocation Size - 336          1,18 GBytes     
Allocation Size - 1120004      121,77 MBytes    
...

Top 5 allocations by count
--------------------------
Allocation Size - 336    3760923 allocation(s) 
Allocation Size - 32     1223794 allocation(s)  
...

明らかに、MSVCR80ヒープは336バイトで3.760.923の割り当てを保持していることがわかります。これにより、メモリを大量の小さな割り当てでモップアップしたことがかなり明確になりますが、これらの割り当てがどこから来たのかに関する詳細情報を取得するにはどうすればよいですか?

どういうわけかこれらの割り当てアドレスのいくつかをサンプリングし、プロセスイメージのどこでこれらのアドレスが使用されているかを確認できれば、これらの割り当ての大部分が「リーク」の原因であると仮定すると、どこにあるかを見つけることができます。これらの暴走した割り当てはから来ました。

残念ながら、現時点では、ダンプからより多くの情報を取得する方法がわかりません。

このヒープを調べて、「336」の割り当てアドレスの一部を確認するにはどうすればよいですか?

これらのアドレスのダンプを検索するにはどうすればよいですか?次に、ダンプ内のどのポインター変数(存在する場合)がこれらのアドレスに保持されているかを見つけるにはどうすればよいですか?

DebugDiag、WinDbg、またはその他のツールの使用に関するヒントがあれば、本当に役に立ちます。また、上記の私の分析のいずれかに同意できない場合は、お知らせください。ありがとう!

21
Martin Ba

あなたは出来る:

  • 336バイトのこれらのブロックを調べて、コンテンツがそれらを割り当てたものについて何かを示しているかどうかを確認します。そのために、私は通常windbgを使用します。まず、ブロックのサイズを指定するコマンド!heap -stat -h 0x01040000を実行してから、このsize!heap -flt ssizeは、そのサイズのすべてのブロックを一覧表示します。次に、メモリを表示する任意のコマンド(dcなど)を使用してブロックを調べることができます。
  • 問題を再現することはできませんが、そのサイズのブロックを割り当てる別のダンプを調べることはできます。まず、gflags.exeutility(gflags -i your.exe +ust)を使用してスタックバックトレース機能をアクティブにします。次に、アプリケーションを実行し、ダンプを取得し、!heap -flt sを使用してブロックを一覧表示します。次に、コマンド!heap -p -ablockaddressは、ブロックを割り当てた関数のスタックをダンプします。
10
plodoc

現在、ダンプはいくつありますか?

メモリリークを追跡する適切な方法は、DebugDiagのメモリとハンドルリークルールをうまく利用することです。

次に、DebugDiagが新しいダンプで機能するときに、メモリ使用量について詳しく知ることができます。

3
Lex Li

Windbgでは、ヒープをクロールする!heap -lを使用して(しばらく時間がかかりますが、検索を特定のヒープに制限して高速化する方法がある場合があります)、参照されていないすべてのビジーブロックを見つけることができます。どこでも。そこからメモリウィンドウを開きます(alt+5)そして、リークの疑いがある割り当てサイズに一致するエントリのいくつかを見てください。運が良ければ、データが何であるかを識別するのに役立ついくつかの一般的なパターンがありますが、すぐに配置できるいくつかのASCII文字列があります。

残念ながら、gflagsでユーザーモードのスタックトレースをオンにし、umdhを使用してメモリスナップショットを取得しながら再現しようとする以外に、他の良い方法はわかりません。

3
Dan