仮想アドレス空間の断片化を調査しています。私が抱えている問題は、への呼び出しVirtualAlloc
が多くのソース (LOH、メモリ マッピングなど) を持つことができることです。
ダンプファイルから関数の呼び出し元を特定できますか? どういうわけか私の問題の原因を突き止めますか?
仮想アドレス空間の断片化を調査しています。私が抱えている問題は、への呼び出しVirtualAlloc
が多くのソース (LOH、メモリ マッピングなど) を持つことができることです。
ダンプファイルから関数の呼び出し元を特定できますか? どういうわけか私の問題の原因を突き止めますか?
アプリの gflags ユーザー スタック トレースを有効にする必要があります。これは、コマンド ラインから、または WinDbg からの場合は WinDbg 内で行うことができます。
!gflag +ust
次に、特定のヒープブロックがより具体的な統計をダンプする必要があります。!heap -s
ここでメモリダンプを実行してから、断片化を引き起こしていることを実行し、押して再度入力してWinDbgに戻り、別のメモリダンプを実行することをお勧めします。!heap -stat -h XX
.dump /ma c:\first.dmp
ctrl+break
!heap -s
.dump /ma c:\second.dmp
メモリ ダンプとヒープ サマリーの理由は、どのヒープが増加または戻っているかを分析し、ダンプを開いてそれらのスナップショットで分析を実行し、結果をテキスト ファイルにダンプし、結果の diff を実行できるためです。
したがって、増加している特定のヒープ ブロックを特定した場合は、そのブロックのすべての割り当てをダンプでき!heap -p -a xxxx
ます。xxxx はヒープ ブロックです。出力をファイルに書き込むように WinDbg をセットアップすることをお勧めします。これは.logfile c:\first.txt
、2 番目のメモリで非常に大きな繰り返しになるためです。ダンプして差分を実行し、追加の割り当てが発生していることを確認します。
また、割り当てサイズの内訳を示すヒープの統計をダンプすることもできます。これも手がかりになる場合があります。とにかく、pdbs にプライベート シンボルがあれば、完全なコール スタックで誰が割り当てを行ったかを特定できます。
編集
役立つ記事があります: http://bugslasher.net/2011/01/15/memory-exhaustion-even-if-a-large-enough-free-memory-segment-is-available/
!pte address
仮想アドレスを取得できる場合は、 を使用して追加情報をダンプできます。pfn frameNum
仮想アドレスのページ フレーム番号は、 の結果から取得できます!pte
。
!vm 1
仮想メモリの使用状況に関するいくつかの統計が表示されますが、それ以上ではありません。もう 1 つは、呼び出しにブレークポイントを設定しvirtualAlloc
、コール スタックとローカル変数をダンプすることです。kf
これを使用すると、スタック フレーム間の距離がバイト単位で表示されます。大きな割り当てを示している可能性があるため、この情報をログ ファイルに書き出し、後で 2 つのダンプ間で比較します。
まず、OSコンポーネントとプログラムにpdbシンボルを設定する必要があります。シンボルパスウィンドウで、次のように文字列を設定します。
srv * f:\ symbol \ websymbols * http://msdl.microsoft.com/download/symbols
プログラムのプライベートシンボルへのパスを追加します。このアクションの後、コマンドkbでpretyスタックトレースを確認できます。スタック内のプログラムの最初の出現は、呼び出し元関数です。