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:
Laden Sie alle Module neu, indem Sie den Befehl .reload (Modul neu laden) verwenden.
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
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:
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.
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'
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
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.