Freigeben über


Verwenden von UMDH zum Finden eines User-Mode Speicherverlusts

Das UMDH-Hilfsprogramm (User Mode Dump Heap) arbeitet mit dem Betriebssystem zusammen, um Windows-Heapzuordnungen für einen bestimmten Prozess zu analysieren. UMDH ermittelt, welche Routine in einem bestimmten Prozess Arbeitsspeicher verloren geht.

UMDH ist in Debugtools für Windows enthalten. Ausführliche Informationen finden Sie unter UMDH.

Vorbereiten der Verwendung von UMDH

Wenn Sie noch nicht ermittelt haben, welcher Prozess Arbeitsspeicherverlust aufweist, führen Sie dies zuerst aus. Weitere Informationen finden Sie unter Verwenden von Leistungsmonitor zum Suchen nach User-Mode Speicherverlusten.

Die wichtigsten Daten in den UMDH-Protokollen sind die Stapelüberwachungen der Heapzuordnungen. Analysieren Sie diese Stapelablaufverfolgungen, um festzustellen, ob ein Prozess Heapspeicher verloren geht.

Bevor Sie UMDH zum Anzeigen der Stapelablaufverfolgungsdaten verwenden, müssen Sie GFlags verwenden, um Ihr System ordnungsgemäß zu konfigurieren. GFlags ist in Debugtools für Windows enthalten.

Die folgenden GFlags-Einstellungen aktivieren UMDH-Stapelüberwachungen:

  • Wählen Sie auf der grafischen GFlags-Benutzeroberfläche die Registerkarte Bilddatei aus, geben Sie den Prozessnamen (einschließlich der Dateinamenerweiterung) ein, drücken Sie die TAB-TASTE, wählen Sie Benutzermodus-Stapelüberwachungsdatenbank erstellen aus, und wählen Sie dann Übernehmen aus.

    Alternativ können Sie auch die folgende GFlags-Befehlszeile verwenden, wobei ImageName der Prozessname ist (einschließlich der Dateinamenerweiterung):

    gflags /i ImageName +ust 
    

    Verwenden Sie diesen Befehl, um die GFlag-Einstellungen zu löschen, sobald Sie fertig sind. Weitere Informationen finden Sie unter GFlags-Befehle.

    gflags /i ImageName -ust 
    
  • Standardmäßig ist die Menge der Stapelüberwachungsdaten, die Windows erfasst, auf 32 MB auf einem x86-Prozessor und 64 MB auf einem x64-Prozessor beschränkt. Wenn Sie die Größe dieser Datenbank erhöhen müssen, wählen Sie die Registerkarte Bilddatei in der grafischen Benutzeroberfläche von GFlags aus, geben Sie den Prozessnamen ein, drücken Sie die TAB-TASTE, aktivieren Sie das Kontrollkästchen Stapelrückverfolgung (Megs), geben Sie einen Wert (in MB) in das zugeordnete Textfeld ein, und wählen Sie dann Übernehmen aus. Erhöhen Sie diese Datenbank nur bei Bedarf, da dadurch möglicherweise begrenzte Windows-Ressourcen verbraucht werden. Wenn Sie die größere Größe nicht mehr benötigen, setzen Sie diese Einstellung auf den ursprünglichen Wert zurück.

  • Wenn Sie flags auf der Registerkarte Systemregistrierung geändert haben, müssen Sie Windows neu starten, damit diese Änderungen wirksam werden. Wenn Sie flags auf der Registerkarte Bilddatei geändert haben, müssen Sie den Prozess neu starten, damit die Änderungen wirksam werden. Änderungen an der Registerkarte Kernelflags werden sofort wirksam, gehen aber beim nächsten Neustart von Windows verloren.

Vor der Verwendung von UMDH müssen Sie Zugriff auf die richtigen Symbole für Ihre Anwendung haben. UMDH verwendet den von der Umgebungsvariablen angegebenen Symbolpfad _NT_SYMBOL_PATH. Legen Sie diese Variable auf einen Pfad fest, der die Symbole für Ihre Anwendung enthält. Wenn Sie auch einen Pfad zu Windows-Symbolen einschließen, ist die Analyse möglicherweise vollständiger. Die Syntax für diesen Symbolpfad entspricht der Syntax, die vom Debugger verwendet wird. Weitere Informationen finden Sie unter Symbolpfad.

Wenn sich z. B. die Symbole für Ihre Anwendung unter C:\MySymbols befinden und Sie den öffentlichen Microsoft-Symbolspeicher für Ihre Windows-Symbole verwenden möchten und C:\MyCache als Downstreamspeicher verwenden, verwenden Sie den folgenden Befehl, um den Symbolpfad festzulegen:

set _NT_SYMBOL_PATH=c:\mysymbols;srv*c:\mycache*https://msdl.microsoft.com/download/symbols 

Darüber hinaus müssen Sie die BSTR-Zwischenspeicherung deaktivieren, um genaue Ergebnisse zu gewährleisten. Legen Sie dazu die OANOCACHE-Umgebungsvariable auf 1 (1) fest. Legen Sie diese Einstellung fest, bevor Sie die Anwendung starten, deren Zuordnungen nachverfolgt werden sollen.

Wenn Sie die von einem Dienst vorgenommenen Zuordnungen nachverfolgen müssen, müssen Sie OANOCACHE als Systemumgebungsvariable festlegen und dann Windows neu starten, damit diese Einstellung wirksam wird.

Erkennen von Erhöhungen der Heapzuordnungen mit UMDH

Nachdem Sie diese Vorbereitungen getroffen haben, können Sie UMDH verwenden, um Informationen zu den Heapzuordnungen eines Prozesses zu erfassen. Gehen Sie dazu wie folgt vor:

  1. Bestimmen Sie die Prozess-ID (PID) für den Prozess, den Sie untersuchen möchten.

  2. Verwenden Sie UMDH, um die Heapspeicherbelegungen für diesen Prozess zu analysieren und in einer Protokolldatei zu speichern. Verwenden Sie den Schalter -p mit der PID und den Schalter -f mit dem Namen der Protokolldatei. Wenn die PID beispielsweise 124 ist und Sie die Protokolldatei Log1.txt benennen möchten, verwenden Sie den folgenden Befehl:

    umdh -p:124 -f:log1.txt 
    
  3. Verwenden Sie Editor oder ein anderes Programm, um die Protokolldatei zu öffnen. Diese Datei enthält die Aufrufliste für jede Heapzuordnung, die Anzahl der über diese Aufrufliste vorgenommenen Zuordnungen und die Anzahl der bytes, die über diese Aufrufliste verbraucht werden.

  4. Da Sie nach einem Speicherverlust suchen, ist der Inhalt einer einzelnen Protokolldatei nicht ausreichend. Sie müssen Protokolldateien vergleichen, die zu unterschiedlichen Zeiten aufgezeichnet wurden, um zu ermitteln, welche Zuordnungen zunimmt.

    UMDH kann zwei verschiedene Protokolldateien vergleichen und die Änderung der jeweiligen Zuordnungsgrößen anzeigen. Sie können das Größer-als-Symbol (>) verwenden, um die Ergebnisse in eine dritte Textdatei umzuleiten. Sie können auch die Option -d einschließen, die die Byte- und Zuordnungsanzahl von hexadezimal in dezimal konvertiert. Verwenden Sie beispielsweise den folgenden Befehl, um Log1.txt und Log2.txt zu vergleichen und die Ergebnisse des Vergleichs in der Datei LogCompare.txt zu speichern:

    umdh log1.txt log2.txt > logcompare.txt 
    
  5. Öffnen Sie die datei LogCompare.txt. Der Inhalt sieht wie folgt aus:

    + 5320 ( f110 - 9df0) 3a allocs BackTrace00B53 
    Total increase == 5320 
    

    Für jede Aufrufliste (mit der Bezeichnung "BackTrace") in den UMDH-Protokolldateien wird ein Vergleich zwischen den beiden Protokolldateien vorgenommen. In diesem Beispiel wurde die erste Protokolldatei (Log1.txt) 0x9DF0 für BackTrace00B53 zugeordneten Bytes aufgezeichnet, während die zweite Protokolldatei 0xF110 Bytes aufgezeichnet hat. Dies bedeutet, dass zwischen dem Zeitpunkt, zu dem die beiden Protokolle erfasst wurden, 0x5320 zusätzliche Bytes zugeordnet wurden. Die Bytes stammen aus der Aufrufliste, die von BackTrace00B53 identifiziert wurde.

  6. Um zu bestimmen, was sich in diesem Backtrace befindet, öffnen Sie eine der ursprünglichen Protokolldateien (z. B. Log2.txt), und suchen Sie nach "BackTrace00B53". Die Ergebnisse ähneln den folgenden Daten:

    00005320 bytes in 0x14 allocations (@ 0x00000428) by: BackTrace00B53
    ntdll!RtlDebugAllocateHeap+0x000000FD
    ntdll!RtlAllocateHeapSlowly+0x0000005A
    ntdll!RtlAllocateHeap+0x00000808
    MyApp!_heap_alloc_base+0x00000069
    MyApp!_heap_alloc_dbg+0x000001A2
    MyApp!_nh_malloc_dbg+0x00000023
    MyApp!_nh_malloc+0x00000016
    MyApp!operator new+0x0000000E
    MyApp!DisplayMyGraphics+0x0000001E
    MyApp!main+0x0000002C
    MyApp!mainCRTStartup+0x000000FC
    KERNEL32!BaseProcessStart+0x0000003D 
    

    Diese UMDH-Ausgabe zeigt, dass 0x5320 (Dezimalzahl 21280) Bytes insgesamt aus der Aufrufliste zugeordnet wurden. Diese Bytes wurden aus 0x14 (dezimalen 20) separaten Zuordnungen von jeweils 0x428 (dezimal 1064) Bytes zugeordnet.

    Die Aufrufliste erhält den Bezeichner "BackTrace00B53", und die Aufrufe in diesem Stapel werden angezeigt. Beim Überprüfen der Aufrufliste sehen Sie, dass die DisplayMyGraphics-Routine Arbeitsspeicher über den neuen Operator zuordnet, der die Malloc-Routine aufruft, die die Visual C++-Laufzeitbibliothek verwendet, um Arbeitsspeicher aus dem Heap abzurufen.

    Bestimmen Sie, welcher dieser Aufrufe der letzte ist, der explizit in Ihrem Quellcode angezeigt wird. In diesem Fall ist es wahrscheinlich der neue Operator, da der Aufruf von malloc im Rahmen der Implementierung von new statt als separate Zuordnung erfolgt ist. Diese instance des neuen Operators in der DisplayMyGraphics-Routine weist also wiederholt Arbeitsspeicher zu, der nicht freigegeben wird.