4

アプリケーションで遅いメモリ リークが発生しました。リークの原因を分析するために、次の手順を既に実行しました。

  1. GFlags でユーザー モード スタック トレース データベースを有効にする
  2. Windbg で、次のコマンドを入力します: !heap -stat -h 1250000 ( 1250000は、リークのあるヒープのアドレスです)流出した記憶。
  3. 次のコマンドを入力します: !heap -flt sc は、これらの割り当ての UserPtr を提供し、最後に:
  4. これらのアドレスの一部に!heap -p -a addressと入力すると、常に次の割り当てコール スタックが表示されます。

0:000> !ヒープ -p -a 10576ef8

address 10576ef8 found in
_HEAP @ 1250000
  HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
    10576ed0 000a 0000  [03]   10576ef8    0000c - (busy)
    mscoreei!CLRRuntimeInfoImpl::`vftable'
    7c94b244 ntdll!RtlAllocateHeapSlowly+0x00000044
    7c919c0c ntdll!RtlAllocateHeap+0x00000e64
    603b14a4 mscoreei!UtilExecutionEngine::ClrHeapAlloc+0x00000014
    603b14cb mscoreei!ClrHeapAlloc+0x00000023
    603b14f7 mscoreei!ClrAllocInProcessHeapBootstrap+0x0000002e
    603b1614 mscoreei!operator new[]+0x0000002b
    603d402b +0x0000005f
    603d5142 mscoreei!GetThunkUseState+0x00000025
    603d6fe8 mscoreei!_CorDllMain+0x00000056
    79015012 mscoree!ShellShim__CorDllMain+0x000000ad
    7c90118a ntdll!LdrpCallInitRoutine+0x00000014
    7c919a6d ntdll!LdrpInitializeThread+0x000000c0
    7c9198e6 ntdll!_LdrpInitialize+0x00000219
    7c90e457 ntdll!KiUserApcDispatcher+0x00000007

これはスレッド初期化コール スタックのように見えますが、これ以上のことを知る必要があります。漏れの正確な原因に指を置くために推奨する次のステップは何ですか.

4

2 に答える 2

6

GFlags の使用時に記録されたスタックは、.pdb を使用せずに行われ、多くの場合正しくありません。特定のヒープの特定のサイズまでリークを追跡したので、RtlAllocateHeap でライブ ブレークを設定し、windbg で適切なシンボルを使用してスタックを調べることができます。私はいくつかの成功を収めて以下を使用しました。ヒープとサイズに合わせて編集する必要があります。

 $$ Display stack if heap handle eq 0x00310000 and size is  0x1303
 $$ ====================================================================
bp ntdll!RtlAllocateHeap "j ((poi(@esp+4) = 0x00310000) & (poi(@esp+c) = 0x1303) )'k';'gc'" 

たぶん、あなたは別のスタックと犯罪者のための他のアイデアを得るでしょう.

于 2012-04-10T10:10:56.967 に答える
2

最初のことは、新しい演算子が演算子であるため、単純な古い呼び出しではなく、new []対応する呼び出しがあるかどうかです。delete[]delete

このコードが疑わしい場合は、テスト ハーネスを配置します。たとえば、ループに入れて 100 回または 1000 回実行しますが、それでもリークし、比例します。

プロセス エクスプローラーを使用して、またはGetProcessInformationを使用してプログラムでメモリの増加を測定することもできます。

もう 1 つの明白なことは、この関数呼び出しをコメント アウトするとどうなるかを確認することです。メモリ リークはなくなりますか? コードをコメントアウトすることで、疑わしいコードを毎回半分 (およそ) 削減するために、可能であればコードのバイナリ チョップを実行する必要があるかもしれませんが、コードの動作を変更すると、より多くの問題や依存するコード パスの問題が発生する可能性があります。メモリ リークや奇妙な動作を引き起こします。

編集 管理された環境で作業しているため、次のことは無視してください。

オブジェクトの有効期間を管理するために、配列構造にshared_ptrSTLscoped_arrayなどの参照カウント ポインター使用することを検討することもできます。

于 2012-04-05T23:15:48.223 に答える