Freigeben über


Ermitteln eines Kernel-Mode Speicherverlusts mithilfe des Kerneldebuggers

Der Kerneldebugger bestimmt den genauen Speicherort eines Speicherverlusts im Kernelmodus.

Aktivieren der Pooltagging

Sie müssen zuerst GFlags verwenden, um die Pooltagging zu aktivieren. GFlags ist in Debugtools für Windows enthalten. Starten Sie GFlags, wählen Sie die Registerkarte Systemregistrierung aus, aktivieren Sie das Kontrollkästchen Pooltagging aktivieren , und wählen Sie dann Anwenden aus. Sie müssen Windows neu starten, damit diese Einstellung wirksam wird.

Unter Windows Server 2003 und höheren Versionen von Windows ist die Pooltagging immer aktiviert.

Ermitteln des Pooltags des Lecks

Um zu bestimmen, welches Pooltag dem Leck zugeordnet ist, ist es in der Regel am einfachsten, das PoolMon-Tool für diesen Schritt zu verwenden. Ausführliche Informationen finden Sie unter Verwenden von PoolMon zum Suchen nach Kernel-Mode Speicherverlusten.

Alternativ können Sie den Kerneldebugger verwenden, um nach Tags zu suchen, die mit großen Poolzuordnungen verknüpft sind. Führen Sie hierzu die folgenden Schritte aus:

  1. Laden Sie alle Module neu, indem Sie den Befehl .reload (Modul neu laden) verwenden.

  2. Verwenden Sie die Erweiterung !poolused . Fügen Sie das Flag "4" ein, um die Ausgabe nach ausgelagerter Speichernutzung zu sortieren:

    kd> !poolused 4 
    Sorting by Paged Pool Consumed
    
    Pool Used:
                NonPaged            Paged     
    Tag    Allocs     Used    Allocs     Used 
    Abc         0        0     36405 33930272 
    Tron        0        0       552  7863232 
    IoN7        0        0     10939   998432 
    Gla5        1      128      2222   924352 
    Ggb         0        0        22   828384 
    
  3. Bestimmen Sie, welches Pooltag mit der größten Arbeitsspeicherauslastung verknüpft ist. In diesem Beispiel verwendet der Treiber, der das Tag "Abc" verwendet, den meisten Arbeitsspeicher ( fast 34 MB). Daher ist der Speicherverlust höchstwahrscheinlich in diesem Treiber.

Auffinden des Lecks

Nachdem Sie das Pooltag ermittelt haben, das dem Leck zugeordnet ist, führen Sie die folgenden Schritte aus, um das Leck selbst zu ermitteln:

  1. Verwenden Sie den Befehl ed (Werte eingeben), um den Wert der globalen Systemvariable PoolHitTag zu ändern. Diese globale Variable bewirkt, dass der Debugger immer dann unterbrochen wird, wenn ein Pooltag verwendet wird, das seinem Wert entspricht.

  2. Legen Sie PoolHitTag gleich dem Tag fest, von dem Sie vermuten, dass es die Quelle des Speicherverlusts ist. Der Modulname "nt" sollte für eine schnellere Symbolauflösung angegeben werden. Der Tagwert muss im Little-Endian-Format (also rückwärts) eingegeben werden. Da Pooltags immer vier Zeichen sind, ist dieses Tag eigentlich A-b-c-space, nicht nur A-b-c. Verwenden Sie daher den folgenden Befehl:

    kd> ed nt!poolhittag ' cbA' 
    
  3. Um den aktuellen Wert von PoolHitTag zu überprüfen, verwenden Sie den Befehl db (Speicher anzeigen):

    kd> db nt!poolhittag L4 
    820f2ba4  41 62 63 20           Abc  
    
  4. Der Debugger wird jedes Mal unterbrochen, wenn dieser Pool mit dem Tag Abc zugewiesen oder freigegeben wird. Verwenden Sie jedes Mal, wenn der Debugger eine dieser Zuordnungen oder freien Vorgänge durchbricht, den Debuggerbefehl kb (Display Stack Backtrace) zum Anzeigen der Stapelablaufverfolgung.

Mit diesem Verfahren können Sie ermitteln, welcher Code im Arbeitsspeicher den Pool mit dem Tag Abc übergibt.

Um den Haltepunkt zu löschen, legen Sie PoolHitTag auf 0 fest:

kd> ed nt!poolhittag 0 

Wenn es mehrere verschiedene Stellen gibt, an denen Arbeitsspeicher mit diesem Tag zugewiesen wird und sich diese in einer Anwendung oder einem Treiber befinden, den Sie geschrieben haben, können Sie Ihren Quellcode so ändern, dass für jede dieser Zuordnungen eindeutige Tags verwendet werden.

Wenn Sie das Programm nicht neu kompilieren können, aber ermitteln möchten, welche von mehreren möglichen Speicherorten im Code das Leck verursacht, können Sie den Code an jedem Speicherort aufheben und den Debugger verwenden, um diesen coderesident im Arbeitsspeicher zu bearbeiten, sodass jeder instance ein eigenes (und zuvor nicht verwendetes) Pooltag verwendet. Lassen Sie dann die Ausführung des Systems für mehrere Minuten oder länger zu. Brechen Sie nach einiger Zeit erneut mit dem Debugger ein, und verwenden Sie die Erweiterung !poolfind , um alle Poolzuordnungen zu finden, die den neuen Tags zugeordnet sind.