2012-04-05 15 views
4

Wir haben einen langsamen Speicherleck in unserer Anwendung, und ich habe bereits durch die folgenden Schritte bei dem Versuch, analyize die Ursache für das Leck gegangen:Untersuchung Speicherverlust

  1. Aktivieren der Benutzermodus-Stack-Trace-Datenbank in GFlags
  2. In Windbg, den folgenden Befehl eingeben: Haufen -stat -h 1250000 (wobei 1250000 die Adresse des Heap ist, dass das Leck hat) Nach einem Vergleich mehrerer Deponien, ich sehe, dass ein Speicherblöcke der Größe 0xC nehmen im Laufe der Zeit zu und sind wahrscheinlich die Erinnerung, die durchgesickert ist.
  3. Sie den folgenden Befehl: Haufen -flt sc gibt die UserPtr dieser Zuweisungen und schließlich:
  4. eingeben heap -p -a Adresse auf einige dieser Adressen immer die folgende Zuordnung Call-Stack :

0: 000>heap -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 

Thi s sieht aus wie Thread-Initialisierung Call-Stack, aber ich muss mehr als das wissen. Was ist der nächste Schritt, den Sie empfehlen würden, um den genauen Grund für das Leck zu finden?

Antwort

2

Die erste Sache ist, dass der neue Operator der Operator new [] ist also gibt es einen entsprechenden delete[] Anruf und nicht eine einfache alte delete Anruf?

Wenn Sie diesen Code vermuten, würde ich einen Test-Kabelbaum um ihn legen, zum Beispiel in eine Schleife stecken und ihn 100 oder 1000 Mal ausführen, ist er immer noch undicht.

Sie können die Speichererweiterung auch mit Process Explorer oder programmgesteuert unter Verwendung von GetProcessInformation messen.

Die andere offensichtliche Sache ist zu sehen, was passiert, wenn Sie diesen Funktionsaufruf auskommentieren, geht das Speicherleck weg? Wenn möglich, müssen Sie einen Binär-Chop durchführen, um den wahrscheinlichen verdächtigen Code jedes Mal um die Hälfte (ungefähr) zu reduzieren, indem Sie Code auskommentieren. Das Ändern des Code-Verhaltens kann jedoch weitere Probleme oder abhängige Codepfad-Probleme verursachen verursachen Speicherlecks oder seltsames Verhalten.

BEARBEITEN Ignorieren Sie das folgende Sehen, da Sie in einer verwalteten Umgebung arbeiten.

Sie auch noch mit den STL oder besser betrachten kann boost Referenz gezählt Zeiger wie shared_ptr oder scoped_array für Array-Strukturen, die Lebensdauer der Objekte zu verwalten.

+0

Während die Sprache nicht angegeben ist, schlägt das Vorhandensein von mscoreei! * Vor, dass dies eine verwaltete Sprache ist, so dass die Notwendigkeit zum Löschen, die Verwendung von STL, Boost usw. wahrscheinlich nicht zutrifft. – jcopenha

+0

Das Problem ist, dass dieser Callstack CLR-Code und nicht meinen Code zeigt, also weiß ich nicht, wo ich suchen soll. – galbarm

+0

Es sieht so aus, als ob es eine DLL lädt, da ich einen dllmain-ähnlichen Anruf sehe, was ist mscoreei? Ich weiß nichts über .net ist das Ihre DLL oder eine dritte Partei, keine MS .net dll? Es ist sehr unwahrscheinlich, dass eine MS-DLL Speicher verliert, so dass es etwas mit falscher Verwendung durch den aufrufenden Code zu tun haben könnte. Sie könnten einen Breakpoint auf die Funktion 'bp mscoreei! GetThunkUseState' setzen und wenn dies aufgerufen wird, den Call-Stack überprüfen und sehen Wenn das Ihnen mehr Informationen gibt als das Post Mortem Dump – EdChum

6

Der Stapel, der bei der Verwendung von GFlags aufgezeichnet wurde, ist ohne Verwendung von .pdb und oft nicht korrekt. Da Sie das Leck auf einem bestimmten Heap auf eine bestimmte Größe zurückverfolgt haben, können Sie versuchen, eine Live-Pause in RtlAllocateHeap und überprüfen Sie den Stapel in Windbg mit geeigneten Symbolen. Ich habe das folgende mit etwas Erfolg verwendet. Sie müssen es bearbeiten, um es Ihrem Heap und Ihrer Größe anzupassen.

$$ 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'" 

Vielleicht bekommen Sie dann einen anderen Stapel und andere Ideen für den Täter.