Share via


Application Verifier – Debuggen der Anwendungsüberprüfung wird beendet

Debuggerinstallation und -einrichtung

Einige Application Verifier-Aktionen können dazu führen, dass eine Ausnahme ausgelöst wird. Der Debugger muss so festgelegt werden, dass er diese Ausnahmen bei der zweiten Chance abfangen kann, da die Anwendungsüberprüfung selbst die Ausnahmen für die erste Chance behandelt.

Die ausgelösten Ausnahmen haben drei Typen:

  • Eine Zugriffsverletzungsausnahme (0xC0000005) wird generiert, wenn die Heapoption einen Heappufferüberlauf erkennt. In einigen Fällen kann die Option Systempfadnutzung überprüfen auch zu einer Zugriffsverletzung führen.

  • Eine Ausnahme mit ungültigem Handle (0xC0000008) wird generiert, wenn die Option Verwendung ungültiger Handle erkennen einen ungültigen Handle-Vorgang erkennt.

  • Eine Stapelüberlaufausnahme (0xC00000FD) wird generiert, wenn die Option Nach geeignetem Stapel suchen erkennt, dass der anfängliche Stapel zu kurz war.

Eine Möglichkeit, sich auf diese Ereignisse vorzubereiten, besteht darin, den Debugger wie folgt über eine Befehlszeile zu starten:

windbg -xd av -xd ch -xd sov ApplicationCommandLine

oder

cdb -xd av -xd ch -xd sov ApplicationCommandLine

Wenn Sie den Debugger bereits gestartet haben, können Sie den Befehl sxd (Ausnahmen festlegen) verwenden, um alle Zugriffsverletzungen, ungültigen Handles und Stapelüberläufe als Ausnahmen für die zweite Chance abzufangen:

0:000> sxd av 

0:000> sxd ch 

0:000> sxd sov 1

Es ist theoretisch möglich, die Application Verifier über einen Kerneldebugger zu steuern. Dies wird jedoch nicht empfohlen. Dies erfordert häufig die Verwendung der Befehle .process und .pagein, aber es bietet Ihnen nicht mehr Leistung als die Verwendung eines Benutzermodusdebuggers.

Installieren der Debugtools

Informationen zum Herunterladen der neuesten Version der Tools finden Sie unter Herunterladen von Debugtools für Windows.

Konfigurieren von Hardware für User-Mode Debuggen

Das Debuggen im Benutzermodus erfolgt in der Regel auf einem einzelnen Computer: Der Debugger wird auf demselben Computer wie die fehlerhafte Anwendung ausgeführt.

In diesem Fall ist keine spezifische Hardwareeinrichtung erforderlich. In diesem Thema sind die Begriffe Hostcomputer und Zielcomputer in diesem Fall austauschbar.

Konfigurieren von Software für User-Mode Debugging

Grundlegende User-Mode Konfiguration: Bevor Sie mit dem Debuggen im Benutzermodus beginnen können, müssen Sie die erforderlichen Symboldateien herunterladen und bestimmte Umgebungsvariablen festlegen.

Symboldateien

Sie müssen die Symboldateien für den Benutzermodusprozess herunterladen, der gerade gedebuggt wird. Wenn es sich um eine von Ihnen geschriebene Anwendung handelt, sollte sie mit vollständigen Symboldateien erstellt werden. Wenn es sich um eine kommerzielle Anwendung handelt, können die Symboldateien auf einem Webserver oder zum Download verfügbar sein. Wenden Sie sich an den Hersteller.

Wenn Sie das Remotedebuggen ausführen, hängt der Speicherort der Symboldatei von der verwendeten Methode ab:

  • Wenn Sie das Remotedebuggen über den Debugger ausführen, sollten sich die Symboldateien auf dem Computer mit dem Debugserver befinden.

  • Wenn Sie das Remotedebuggen über remote.exe ausführen, sollten sich die Symboldateien auf dem Computer mit dem Debugger befinden.

  • Wenn Sie das Remotedebuggen über einen Prozessserver oder einen KD-Verbindungsserver durchführen, sollten sich die Symboldateien auf einem Computer mit dem smarten Client befinden.

  • Wenn Sie den Benutzermodusdebugger über den Kerneldebugger steuern, müssen sich die Symboldateien auf beiden Computern befinden.

Konfigurieren von Umgebungsvariablen

Der Debugger verwendet eine Vielzahl von Umgebungsvariablen, um eine Reihe wichtiger Einstellungen anzugeben.

Weitere Informationen zu Debuggern finden Sie unter Erste Schritte mit Windows-Debugging.

Konfigurieren der Application Verifier mit dem Debugger über die Befehlszeile

Zum Konfigurieren von Application Verifier können Sie die CDB- oder NTSD-Befehlszeile verwenden.

Verwenden Sie die folgende Befehlszeile:

cdb OtherOptions -vf:Flags Target

Dabei ist Target der Name der Zielanwendung und Flags gibt die gewünschten Optionen für die Anwendungsüberprüfung an, die auf dieses Ziel angewendet werden sollen.

Flags sollten eine Summe der Bits sein, die die gewünschten Optionen darstellen. Die einzelnen Bitwerte sind wie folgt:

Flagwert Bedeutung
00000001 HEAP-ÜBERPRÜFUNGEN
00000004 BEHANDELN VON ÜBERPRÜFUNGEN
00000008 SIM-ÜBERPRÜFUNGEN MIT GERINGEN RESSOURCEN
00000020 TLS-ÜBERPRÜFUNGEN
00000040 DIRTY STACKS
00000200 GEFÄHRLICHE APIS
00001000 AUSNAHMEPRÜFUNGEN
00002000 SPEICHERÜBERPRÜFUNGEN
00020000 VERSCHIEDENE ÜBERPRÜFUNGEN
00040000 SPERRÜBERPRÜFUNGEN

Debuggen mit !avrf

Die Erweiterung !avrf steuert die Einstellungen von Application Verifier und zeigt eine Vielzahl von Ausgaben an, die von Application Verifier erzeugt werden. Weitere Informationen zur Erweiterung !arvrf finden Sie unter !avrf in der Debuggerdokumentation.

Syntax

!avrf

Der Befehl !avrf ohne Parameter zeigt die Anwendungsüberprüfungseinstellungen und Informationen zu den aktuellen und vorherigen Application Verifier-Unterbrechungen an, falls vorhanden.

!avrf –vs { Length | -aAddress }

Zeigt das Vorgangsprotokoll des virtuellen Raums an. Length gibt die Anzahl der Datensätze an, die ab dem letzten angezeigt werden sollen. Address gibt die virtuelle Adresse an. Datensätze der virtuellen Vorgänge, die diese virtuelle Adresse enthalten, werden angezeigt.

!avrf -hp { Length | -a Address }

Zeigt das Heapvorgangsprotokoll an. Address gibt die Heapadresse an. Datensätze der Heapvorgänge, die diese Heapadresse enthalten, werden angezeigt.

!avrf -cs { Length | -a Address }

Zeigt das Löschprotokoll des kritischen Abschnitts an. Length gibt die Anzahl der Datensätze an, die ab dem letzten angezeigt werden sollen. Address gibt die Adresse des kritischen Abschnitts an. Datensätze für den bestimmten kritischen Abschnitt werden angezeigt, wenn Adresse angegeben wird.

!avrf -dlls [ Length ]

Zeigt das DLL-Lade-/Entladeprotokoll an. Length gibt die Anzahl der Datensätze an, die ab dem letzten angezeigt werden sollen.

!avrf -trm

Zeigt ein Protokoll aller beendeten und angehaltenen Threads an.

!avrf -ex [ Length ]

Zeigt das Ausnahmeprotokoll an. Application Verifier verfolgt alle Ausnahmen, die in der Anwendung auftreten.

!avrf -threads [ ThreadID ]

Zeigt Informationen zu Threads im Zielprozess an. Für untergeordnete Threads werden auch die Stapelgröße und die vom übergeordneten Element angegebenen CreateThread-Flags angezeigt. Wenn Sie eine Thread-ID angeben, werden nur Informationen für diesen bestimmten Thread angezeigt.

!avrf -tp [ ThreadID ]

Zeigt das Threadpoolprotokoll an. Dieses Protokoll kann Stapelüberwachungen für verschiedene Vorgänge enthalten, z. B. das Ändern der Threadaffinitätsmaske, das Ändern der Threadpriorität, das Posten von Threadnachrichten, das Initialisieren von COM und das Aufheben der Initialisierung von COM innerhalb des Threadpoolrückrufs. Wenn Sie eine Thread-ID angeben, werden nur Informationen für diesen bestimmten Thread angezeigt.

!avrf -srw [ Address | Address Length ] [ -stats ]

Zeigt das SRW-Protokoll (Slim Reader/Writer) an. Wenn Sie Adresse angeben, werden Datensätze angezeigt, die sich auf diese SRW-Sperradresse beziehen. Wenn Länge zusammen mit der Adresse angegeben wird, werden alle SRW-Sperren innerhalb dieses Adressbereichs angezeigt. Die Option -stats gibt die SRW-Sperrstatistiken ab.

!avrf -leak [ -m ModuleName ] [ -r ResourceType ] [ -a Address ] [ -t ]

Zeigt das Ausstehende Ressourcenprotokoll an. Diese Ressourcen können zu einem bestimmten Zeitpunkt Lecks sein oder auch nicht. Wenn Sie ModuleName (einschließlich der Erweiterung) angeben, werden alle ausstehenden Ressourcen im angegebenen Modul angezeigt. Wenn Sie ResourceType angeben, werden ausstehende Ressourcen des jeweiligen Ressourcentyps angezeigt. Das Angeben von Adressabbildern enthält Datensätze ausstehender Ressourcen mit dieser Adresse. ResourceType kann eine der folgenden Elemente sein:

  • Heap: Zeigt Heapzuordnungen mithilfe von Win32-Heap-APIs an
  • Lokal: Zeigt lokale/globale Zuordnungen an
  • CRT: Zeigt Zuordnungen mithilfe von CRT-APIs an
  • Virtual: Zeigt virtuelle Reservierungen an
  • BSTR: Zeigt BSTR-Zuordnungen an
  • Registrierung: Zeigt registrierungsschlüssel geöffnet an
  • Power: Zeigt Energiebenachrichtigungsobjekte an
  • Handle: Zeigt Thread-, Datei- und Ereignishandlezuordnungen an

!avrf –trace TraceIndex

Zeigt eine Stapelablaufverfolgung für den angegebenen Ablaufverfolgungsindex an. Einige Strukturen verwenden diese 16-Bit-Indexnummer, um eine Stapelablaufverfolgung zu identifizieren. Dieser Index verweist auf einen Speicherort in der Stapelablaufverfolgungsdatenbank. Wenn Sie eine solche Struktur analysieren, finden Sie diese Syntax nützlich.

!avrf -cnt

Zeigt eine Liste globaler Leistungsindikatoren an.

!avrf -brk [ BreakEventType ]

Gibt an, dass es sich um einen Break-Event-Befehl handelt. Wenn !avrf -brk keine zusätzlichen Parameter verwendet werden, werden die Einstellungen für das Unterbrechungsereignis angezeigt. BreakEventType gibt die Typnummer des Umbruchereignisses an. Verwenden Sie !avrf -brkfür eine Liste der möglichen Typen .

!avrf -flt [ EventTypeProbability ]

Gibt an, dass es sich um einen Fehlereinschleusungsbefehl handelt. Wenn !avrf -flt ohne zusätzliche Parameter verwendet wird, werden die aktuellen Fehlereinschleusungseinstellungen angezeigt. EventType gibt die Typnummer des Ereignisses an. Wahrscheinlichkeit gibt die Häufigkeit an, mit der das Ereignis fehlschlägt. Dies kann eine beliebige ganze Zahl zwischen 0 und 1.000.000 (0xF4240) sein.

!avrf -flt break EventType

Bewirkt, dass die Anwendungsüberprüfung jedes Mal in den Debugger einbricht, wenn dieser Fehler eingefügt wird.

!avrf -flt stacks Length

Zeigt die Längenanzahl der Stapelablaufverfolgungen für die zuletzt fehlerinjizierten Vorgänge an.

!avrf -trg [ StartEnd | dll Module | all ]

Gibt an, dass es sich um einen Zielbereichsbefehl handelt. Wenn -trg ohne zusätzliche Parameter verwendet wird, werden die aktuellen Zielbereiche angezeigt. Start gibt die Anfangsadresse des Ziel- oder Ausschlussbereichs an. End gibt die Endadresse des Ziel- oder Ausschlussbereichs an. Module gibt den Namen eines Moduls an, das als Ziel oder ausgeschlossen werden soll. Das Modul sollte den vollständigen Modulnamen enthalten, einschließlich der .exe- oder .dll-Erweiterung. Pfadinformationen sollten nicht enthalten sein. Wenn Sie alle angeben, werden alle Zielbereiche oder Ausschlussbereiche zurückgesetzt.

!avrf -skp [ StartEnd | dll Module | all | Time ]

Gibt an, dass es sich um einen Ausschlussbereichsbefehl handelt. Start gibt die Anfangsadresse des Ziel- oder Ausschlussbereichs an. End gibt die Endadresse des Ziel- oder Ausschlussbereichs an. Module gibt den Namen eines Moduls an, das als Ziel oder ausgeschlossen werden soll. Das Modul sollte den vollständigen Modulnamen enthalten, einschließlich der .exe- oder .dll-Erweiterung. Pfadinformationen sollten nicht enthalten sein. Wenn Sie alle angeben, werden alle Zielbereiche oder Ausschlussbereiche zurückgesetzt. Die Angabe von Time bewirkt, dass alle Fehler für Zeit-Millisekunden unterdrückt werden, nachdem die Ausführung fortgesetzt wurde.

Im Folgenden finden Sie die Ausgabe, die vom Befehl !avrf im Debugger bereitgestellt wird.

0:000> !avrf
Application verifier settings (816431A7):

   - full page heap
   - COM
   - RPC
   - Handles
   - Locks
   - Memory
   - TLS
   - Exceptions
   - Threadpool
   - Leak
   - SRWLock

No verifier stop active.

Note: Sometimes bugs found by verifier manifest themselves as raised
exceptions (access violations, stack overflows, invalid handles), 
and it is not always necessary to have a verifier stop.

Kommentare der !avrf-Erweiterung

Wenn die Erweiterung !avrf ohne Parameter verwendet wird, werden die aktuellen Optionen für die Anwendungsüberprüfung angezeigt.

Die Erweiterung !avrf verwendet die Exts.dll im Debugger.

Wenn ein Application Verifier-Stopp aufgetreten ist, zeigt die !avrf-Erweiterung ohne Parameter die Art des Stopps und die Ursache an.

Wenn Symbole für ntdll.dll und verifier.dll fehlen, generiert die Erweiterung !avrf eine Fehlermeldung.

Fortlaufende und nicht fortsetzbare Stopps

Debuggen eines fortlaufenden Stopps

Hier sehen Sie ein Beispiel für eine ungültige Handle-Ausnahme, die von der Option Ungültige Handlenutzung erkennen ausgelöst wurde.

Zunächst wird die folgende Meldung angezeigt:

Invalid handle - code c0000008 (first chance)

===================================================

VERIFIER STOP 00000300: pid 0x558: invalid handle exception for current stack trace

        C0000008 : Exception code.

        0012FBF8 : Exception record. Use .exr to display it.

        0012FC0C : Context record. Use .cxr to display it.

        00000000 :

===================================================

This verifier stop is continuable.

After debugging it use 'go' to continue.

===================================================

Break instruction exception - code 80000003 (first chance)

eax=00000000 ebx=6a27c280 ecx=6a226447 edx=0012fa4c esi=00942528 edi=6a27c260

eip=6a22629c esp=0012facc ebp=0012faf0 iopl=0         nv up ei pl zr na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

ntdll!DbgBreakPoint:

6a22629c cc               int     3

Beachten Sie, dass Sie in der Meldung erfahren, dass dieser Application Verifier-Stopp fortgesetzt werden kann. Nachdem Sie verstanden haben, was sich herausgestellt hat, können Sie die Zielanwendung weiter ausführen.

Zunächst sollten Sie die Erweiterung !avrf verwenden. Dadurch erhalten Sie Informationen zum aktuellen Fehler:

0:000> !avrf

Global flags: 00000100

Application verifier global flag is set.

Application verifier settings (00000004):

   - no heap checking enabled!

   - handle checks

Page heap is not active for this process.

Current stop 00000300 : c0000008 0012fbf8 0012fc0c 00000000 .

    Using an invalid handle (either closed or simply bad).

In der letzten Zeile dieser Anzeige wird das Problem zusammengefasst.

Möglicherweise sollten Sie sich an dieser Stelle einige Protokolle ansehen. Nachdem Sie fertig sind, verwenden Sie den Befehl g (Go), um die Anwendung erneut zu starten:

0:000> g

## Debugging a Non-Continuable Stop

Here is an example of an access violation that has been raised by the page heap option.

First, the following message appears:

Access violation - code c0000005 (first chance)

===================================================

VERIFIER STOP 00000008: pid 0x504: exception raised while verifying block header

        00EC1000 : Heap handle

        00F10FF8 : Heap block

        00000000 : Block size

        00000000 :

===================================================

This verifier stop is not continuable. Process will be terminated when you use the 'go' debugger command.

===================================================

Break instruction exception - code 80000003 (first chance)

eax=00000000 ebx=00000000 ecx=6a226447 edx=0012fab7 esi=00f10ff8 edi=00000008

eip=6a22629c esp=0012fb5c ebp=0012fb80 iopl=0         nv up ei pl zr na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

ntdll!DbgBreakPoint:

6a22629c cc               int     3

In diesem Fall wird Ihnen in der Meldung mitgeteilt, dass dieser Anwendungsüberprüfungsstopp nicht fortgesetzt werden kann. Der Fehler ist zu schwerwiegend, damit der Prozess weiter ausgeführt werden kann, und es gibt keine Möglichkeit für Application Verifier, den Prozess zu retten.

Die Erweiterung !avrf kann verwendet werden, um Informationen zum aktuellen Fehler zu geben:

0:000> !avrf

Global flags: 02000100

Application verifier global flag is set.

Page heap global flag is set.

Application verifier settings (00000001):

   - full page heap

Page heaps active in the process (format: pageheap, lightheap, flags):

    00941000 , 00a40000 , 3 (pageheap traces )

    00b41000 , 00c40000 , 3 (pageheap traces )

    00cb1000 , 00db0000 , 3 (pageheap traces )

    00ec1000 , 00fc0000 , 3 (pageheap traces )

Current stop 00000008 : 00ec1000 00f10ff8 00000000 00000000 .

    Corrupted heap block.

In der letzten Zeile dieser Anzeige wird das Problem zusammengefasst.

Möglicherweise sollten Sie sich an dieser Stelle auch einige Protokolle ansehen. Sie können an diesem Punkt den Befehl NEUSTART (Zielanwendung neu starten) verwenden. Oder vielleicht bevorzugen Sie es, Ihre Application Verifier-Sitzung zu beenden und mit der Behebung der Fehler in Ihrem Code zu beginnen.

Debuggen kritischer Abschnittsfehler

!cs-Debuggererweiterung

!cs kann sowohl im Benutzermodusdebugger als auch im Kerneldebugger verwendet werden, um Informationen zu wichtigen Abschnitten im aktuellen Prozess anzuzeigen. Weitere Informationen zur Erweiterung !cs finden Sie unter !cs in der Debuggerdokumentation.

Der Abgleich von Symbolen mit Typinformationen ist insbesondere für ntdll.dll erforderlich.

Die Syntax für diese Erweiterung lautet:

!cs [-s] – Führen Sie alle aktiven kritischen Abschnitte im aktuellen Prozess aus.

!cs [-s] address: Enthält einen kritischen Abschnitt an dieser Adresse.

!cs [-s] -d address : Dumpkritisch, der DebugInfo an dieser Adresse entspricht.

-s gibt die Stapelablaufverfolgung des kritischen Abschnitts ab, wenn sie verfügbar ist.

Beispiele:

Informationen zu einem kritischen Abschnitt mithilfe seiner Adresse abspeichern

0:001> ! cs 0x7803B0F8

Critical section   = 0x7803B0F8 (MSVCRT!__app_type+0x4)
DebugInfo          = 0x6A262080
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0

Abspeichern von Informationen zu einem kritischen Abschnitt mithilfe seiner Adresse, einschließlich Der Ablaufverfolgung des Initialisierungsstapels

0:001> !cs -s 0x7803B0F8

Critical section   = 0x7803B0F8 (MSVCRT!__app_type+0x4)
DebugInfo          = 0x6A262080
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0

Stack trace for DebugInfo = 0x6A262080:
0x6A2137BD: ntdll!RtlInitializeCriticalSectionAndSpinCount+0x9B
0x6A207A4C: ntdll!LdrpCallInitRoutine+0x14
0x6A205569: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DCE1: ntdll!LdrpInitializeProcess+0xAE5

Abspeichern von Informationen zu einem kritischen Abschnitt mithilfe seiner Debuginformationsadresse

0:001> !cs -d 0x6A262080

DebugInfo          = 0x6A262080
Critical section   = 0x7803B0F8 (MSVCRT!__app_type+0x4)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0

Abspeichern von Informationen zu einem kritischen Abschnitt mithilfe seiner Debuginformationsadresse, einschließlich Der Ablaufverfolgung des Initialisierungsstapels

0:001> !cs -s -d 0x6A262080

DebugInfo          = 0x6A262080
Critical section   = 0x7803B0F8 (MSVCRT!__app_type+0x4)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
Stack trace for DebugInfo = 0x6A262080:
0x6A2137BD: ntdll!RtlInitializeCriticalSectionAndSpinCount+0x9B
0x6A207A4C: ntdll!LdrpCallInitRoutine+0x14
0x6A205569: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DCE1: ntdll!LdrpInitializeProcess+0xAE

Informationen zu allen aktiven kritischen Abschnitten im aktuellen Prozess abspeichern

0:001> !cs

-----------------------------------------

DebugInfo          = 0x6A261D60
Critical section   = 0x6A262820 (ntdll!RtlCriticalSectionLock+0x0)
LOCKED
LockCount          = 0x0
OwningThread       = 0x460
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x0
-----------------------------------------

DebugInfo          = 0x6A261D80
Critical section   = 0x6A262580 (ntdll!DeferedCriticalSection+0x0)
NOT LOCKED
LockSemaphore      = 0x7FC
SpinCount          = 0x0
-----------------------------------------

DebugInfo          = 0x6A262600
Critical section   = 0x6A26074C (ntdll!LoaderLock+0x0)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
.....

Abspeichern von Informationen zu allen aktiven kritischen Abschnitten im aktuellen Prozess, einschließlich Der Ablaufverfolgung des Initialisierungsstapels


0:001> !cs -s

...

-----------------------------------------

DebugInfo          = 0x6A261EA0
Critical section   = 0xA8001C (+0xA8001C)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
No stack trace saved

-----------------------------------------

DebugInfo          = 0x6A261EC0
Critical section   = 0x6A263560 (ntdll!RtlpDphTargetDllsLock+0x0)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
No stack trace saved

-----------------------------------------

DebugInfo          = 0x6A261EE0
Critical section   = 0xA90608 (+0xA90608)
NOT LOCKED
LockSemaphore      = 0x7EC
SpinCount          = 0x0
Stack trace for DebugInfo = 0x6A261EE0:

0x6A2137BD: ntdll!RtlInitializeCriticalSectionAndSpinCount+0x9B
0x6A20B0DC: ntdll!CsrpConnectToServer+0x1BE
0x6A20B2AA: ntdll!CsrClientConnectToServer+0x148
0x77DBE83F: KERNEL32!BaseDllInitialize+0x11F
0x6A207A4C: ntdll!LdrpCallInitRoutine+0x14
0x6A205569: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DCE1: ntdll!LdrpInitializeProcess+0xAE5

-----------------------------------------

DebugInfo          = 0x6A261F00
Critical section   = 0x77E1AEB8 (KERNEL32!BaseDllRegistryCache+0x18)
NOT LOCKED
LockSemaphore      = 0x0
SpinCount          = 0x0
Stack trace for DebugInfo = 0x6A261F00:
0x6A2137BD: ntdll!RtlInitializeCriticalSectionAndSpinCount+0x9B
0x6A207A4C: ntdll!LdrpCallInitRoutine+0x14
0x6A205569: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DCE1: ntdll!LdrpInitializeProcess+0xAE5

Debuggen von Ausnahmefehlern

Das Ausnahmeprotokoll zeichnet alle Ausnahmen auf, die im Zielprozess aufgetreten sind.

Sie können den Erweiterungsbefehl !avrf -ex Length verwenden, um die letzten Ausnahmen anzuzeigen. Length gibt die Anzahl der Ausnahmen an. Wenn Length ausgelassen wird, werden alle Ausnahmen angezeigt.

Beispiel:

0:000> !avrf -ex 4

=================================

Thread ID: 0000052c
Exception code: c0000008
Exception address: 6a226663
Exception record: 0012fb50
Context record: 0012fb64

Displayed 1 exception log entries.

Debuggen behandelt Fehler

!htrace kann sowohl im Benutzermodusdebugger als auch im Kerneldebugger verwendet werden, um Stapelablaufverfolgungsinformationen für einen oder alle Handles in einem Prozess anzuzeigen. Diese Informationen sind verfügbar, wenn die Handle-Ablaufverfolgung für den Prozess aktiviert ist – automatisch aktiviert, wenn die Handle-Überprüfung in der Anwendungsüberprüfung aktiviert ist. Stapelablaufverfolgungen werden jedes Mal gespeichert, wenn der Prozess ein Handle öffnet oder schließt oder wenn er auf ein ungültiges Handle verweist. Weitere Informationen zur Erweiterung !htrace finden Sie in der Debuggerdokumentation unter !htrace .

Die Kerneldebuggersyntax für diese Erweiterung lautet:

!htrace [ handle [process] ]

Wenn handle nicht angegeben oder 0 ist, werden Informationen zu allen Handles im Prozess angezeigt. Wenn der Prozess nicht angegeben ist, wird der aktuelle Prozess verwendet.

Die Syntax des Benutzermodusdebuggers lautet:

!htrace [handle]

Die Benutzermodusdebuggererweiterung zeigt immer Informationen zum aktuellen Debugprozess an.

Beispiele:

Speicherabbildinformationen zu Handle 7CC in Prozess 815328b0

kd> !htrace 7CC 815328b0

Loaded \\...\kdexts extension DLL
Process 0x815328B0
ObjectTable 0xE15ECBB8

--------------------------------------

Handle 0x7CC - CLOSE:
0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x77DBFCD6: KERNEL32!GetLocaleFileInfo+0x3D
0x77DBF942: KERNEL32!NlsProcessInitialize+0x11D
0x77E0C6DF: KERNEL32!NlsDllInitialize+0x35
0x6A20785C: ntdll!LdrpCallInitRoutine+0x14
0x6A205393: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DD80: ntdll!LdrpInitializeProcess+0xAF6

--------------------------------------

Handle 0x7CC - OPEN:

0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3180: ntoskrnl!ObpCreateHandle+0x304
0x801E1563: ntoskrnl!ObOpenObjectByName+0x1E9
0x77DBFCD6: KERNEL32!GetLocaleFileInfo+0x3D
0x77DBF942: KERNEL32!NlsProcessInitialize+0x11D
0x77E0C6DF: KERNEL32!NlsDllInitialize+0x35
0x6A20785C: ntdll!LdrpCallInitRoutine+0x14
0x6A205393: ntdll!LdrpRunInitializeRoutines+0x1D9
0x6A20DD80: ntdll!LdrpInitializeProcess+0xAF6

--------------------------------------

Parsed 0x1CA stack traces.
Dumped 0x2 stack traces.

Speicherabbildinformationen zu allen Handles in Prozess 815328b0

kd> !htrace 0 81400300

Process 0x81400300
ObjectTable 0xE10CCF60

--------------------------------------

Handle 0x7CC - CLOSE:
0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7CC - OPEN:

0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3390: ntoskrnl!ObpCreateUnnamedHandle+0x10C
0x801E7317: ntoskrnl!ObInsertObject+0xC3
0x77DE23B2: KERNEL32!CreateSemaphoreA+0x66
0x010011C5: badhandle!main+0x45
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7DC - BAD REFERENCE:

0x8018F709: ntoskrnl!ExMapHandleToPointerEx+0xEA
0x801E10F2: ntoskrnl!ObReferenceObjectByHandle+0x12C
0x801902BE: ntoskrnl!NtSetEvent+0x6C
0x80154965: ntoskrnl!_KiSystemService+0xC4
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7DC - CLOSE:

0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7DC - OPEN:

0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3390: ntoskrnl!ObpCreateUnnamedHandle+0x10C
0x801E7317: ntoskrnl!ObInsertObject+0xC3
0x77DE265C: KERNEL32!CreateEventA+0x66
0x010011A0: badhandle!main+0x20
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Parsed 0x6 stack traces.

Dumped 0x5 stack traces.

Speicherabbildinformationen zum Handle 7DC im aktuellen Prozess


kd> !htrace  7DC

Process 0x81400300

ObjectTable 0xE10CCF60

--------------------------------------

Handle 0x7DC - BAD REFERENCE:

0x8018F709: ntoskrnl!ExMapHandleToPointerEx+0xEA
0x801E10F2: ntoskrnl!ObReferenceObjectByHandle+0x12C
0x801902BE: ntoskrnl!NtSetEvent+0x6C
0x80154965: ntoskrnl!_KiSystemService+0xC4
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7DC - CLOSE:

0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Handle 0x7DC - OPEN:

0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3390: ntoskrnl!ObpCreateUnnamedHandle+0x10C
0x801E7317: ntoskrnl!ObInsertObject+0xC3
0x77DE265C: KERNEL32!CreateEventA+0x66
0x010011A0: badhandle!main+0x20
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D

--------------------------------------

Parsed 0x6 stack traces.

Dumped 0x3 stack traces.

Debuggen von Heapfehlern

Debuggererweiterung für die Heapüberprüfung

Die Debuggererweiterung für die Heapüberprüfung ist Teil der Erweiterung !heap (NT-Heapdebuggererweiterung). Einfache Hilfe erhalten Sie mit !heap -? oder umfangreicher mit !heap -p -? . Die aktuelle Erweiterung erkennt nicht selbst, ob seitenheap für einen Prozess aktiviert ist, und handelt entsprechend. Vorerst muss der Benutzer der Erweiterung wissen, dass der Seitenheap aktiviert ist, und Befehle verwenden, die mit dem Präfix !heap -p versehen sind. Weitere Informationen zur !htrace-Erweiterung finden Sie unter !heap in der Debuggerdokumentation.

!heap -p

Speicherabbilder aller ganzseitigen Heaps, die im Prozess erstellt wurden.

!heap -p -h ADDRESS-OF-HEAP

Vollständiges Abbild des Ganzseitenheaps unter ADDRESS-OF-HEAP.

!heap -p -a ADDRESS

Versucht herauszufinden, ob bei ADDRESS ein Heapblock vorhanden ist. Dieser Wert muss nicht die Adresse des Anfangs des Blocks sein. Der Befehl ist nützlich, wenn überhaupt kein Hinweis auf die Art eines Speicherbereichs vorhanden ist.

Heap-Vorgangsprotokoll

Im Heapvorgangsprotokoll werden alle Heaproutinen nachverfolgt. Dazu gehören HeapAlloc, HeapReAlloc und HeapFree.

Sie können den Erweiterungsbefehl !avrf -hp Length verwenden, um die letzten Datensätze anzuzeigen. Length gibt die Anzahl der Datensätze an.

Sie können verwenden !avrf -hp -a Address , um alle Heapspeicherplatzvorgänge anzuzeigen, die sich auf die angegebene Adresse auswirken. Für einen Zuordnungsvorgang reicht es aus, dass Address im zugeordneten Heapblock enthalten ist. Für einen freien Vorgang muss die genaue Adresse des Anfangs des Blocks angegeben werden.

Für jeden Eintrag im Protokoll werden die folgenden Informationen angezeigt:

  • Die Heapfunktion wird aufgerufen.
  • Die Thread-ID des Threads, der die Routine aufgerufen hat.
  • Die Adresse, die am Anruf beteiligt ist– dies ist die Adresse, die von einer Zuordnungsroutine zurückgegeben oder an eine freie Routine übergeben wurde.
  • Die Größe der am Anruf beteiligten Region.
  • Die Stapelablaufverfolgung des Aufrufs.

Die neuesten Einträge werden zuerst angezeigt.

In diesem Beispiel werden die beiden letzten Einträge angezeigt:

0:001> !avrf -hp 2

alloc (tid: 0xFF4): 
address: 00ea2fd0 
size: 00001030
00403062: Prymes!_heap_alloc_dbg+0x1A2
00402e69: Prymes!_nh_malloc_dbg+0x19
00402e1e: Prymes!_malloc_dbg+0x1E
00404ff3: Prymes!_stbuf+0xC3
00401c23: Prymes!printf+0x43
00401109: Prymes!main+0xC9
00402039: Prymes!mainCRTStartup+0xE9
77e7a278: kernel32!BaseProcessStart+0x23

alloc (tid: 0xFF4): 
address: 00ea07d0 
size: 00000830
00403062: Prymes!_heap_alloc_dbg+0x1A2
00402e69: Prymes!_nh_malloc_dbg+0x19
00402e1e: Prymes!_malloc_dbg+0x1E
00403225: Prymes!_calloc_dbg+0x25
00401ad5: Prymes!__initstdio+0x45
00401f38: Prymes!_initterm+0x18
00401da1: Prymes!_cinit+0x21
00402014: Prymes!mainCRTStartup+0xC4

77e7a278: kernel32!BaseProcessStart+0x23

Typische Debugszenarien

Es gibt mehrere Fehlerszenarien, die auftreten können. Einige von ihnen erfordern einige detektivische Arbeit, um das ganze Bild zu bekommen.

Zugriffsverletzung auf nicht zugänglicher Seite

Dies geschieht, wenn der ganzseitige Heap aktiviert ist, wenn die getestete Anwendung über das Ende des Puffers zugreift. Es kann auch passieren, wenn es einen freigegebenen Block berührt. Um die Art der Adresse zu verstehen, für die die Ausnahme aufgetreten ist, müssen Sie Folgendes verwenden:

!heap –p –a ADDRESS-OF-AV

Beschädigte Blocknachricht

In mehreren Momenten während der Lebensdauer einer Zuordnung (Zuordnung, benutzerfrei, real kostenlos) überprüft der Seitenheap-Manager, ob der Block alle Füllmuster intakt hat und der Blockheader konsistente Daten enthält. Wenn dies nicht der Fall ist, erhalten Sie einen Prüferstopp.

Wenn der Block ein ganzseitiger Heapblock ist (wenn Sie z. B. wissen, dass der ganze Seitenheap für alle Zuordnungen aktiviert ist), können Sie "!heap –p –a ADDRESS" verwenden, um herauszufinden, welche Merkmale der Block aufweist.

Wenn es sich bei dem Block um einen hellen Seitenheapblock handelt, müssen Sie die Startadresse für den Blockheader ermitteln. Sie können die Startadresse finden, indem Sie 30-40 Bytes unter die gemeldete Adresse geben und nach den magischen Start/End-Mustern für einen Blockheader suchen (ABCDAAAA, ABCDBBBB, ABCDAAA9, ABCDBBBA).

Der Header enthält alle Informationen, die Sie benötigen, um den Fehler zu verstehen. Insbesondere zeigen die magischen Muster an, ob der Block zugeordnet oder frei ist, wenn es sich um einen hellen Seitenheap oder einen ganzseitigen Heapblock handelt. Die Informationen hier müssen sorgfältig mit dem beleidigenden Aufruf abgeglichen werden.

Wenn beispielsweise ein Aufruf von HeapFree mit der Adresse eines Blocks plus vier Bytes erfolgt, erhalten Sie die beschädigte Nachricht. Der Blockheader sieht in Ordnung aus, aber Sie müssen feststellen, dass das erste Byte nach dem Ende des Headers (erstes Byte nach dem Magic-Wert 0xDCBAXXXX) eine andere Adresse als die im Aufruf hat.

Spezielle Füllzeiger

Der Seitenheap-Manager füllt die Benutzerzuordnung mit Werten aus, die als Kernelzeiger aussehen. Dies geschieht, wenn der Block freigegeben wird (Füllwert ist F0) und wenn der Block zugeordnet wird, aber keine Anforderung für den Block auf Null gestellt wird (Füllwert ist E0 für den hellen Seitenheap und C0 für ganzseitigen Heap). Die Zuordnungen ohne Null sind typisch für malloc/new-Benutzer. Wenn es einen Fehler (Zugriffsverletzung) gibt, bei dem ein Lese-/Schreibversuch für Adressen wie F0F0F0F0, E0E0E0E0, C0C0C0C0 wird höchstwahrscheinlich einer dieser Fälle angezeigt.

Ein Lese-/Schreibzugriff bei F0F0F0F0 bedeutet, dass ein Block verwendet wurde, nachdem er freigegeben wurde. Leider benötigen Sie einige Detektivarbeit, um herauszufinden, welcher Block dies verursacht hat. Sie müssen die Stapelüberwachung des Fehlers abrufen und dann den Code auf die Funktionen im Stapel untersuchen. Einer von ihnen könnte eine falsche Annahme treffen, dass eine Zuordnung am Leben ist.

Ein Lese-/Schreibzugriff bei E0E0E0E0/C0C0C0C0 bedeutet, dass die Anwendung die Zuordnung nicht ordnungsgemäß initialisiert hat. Dies erfordert auch die Codeüberprüfung der Funktionen in der aktuellen Stapelüberwachung. Hier ist es ein Beispiel für diese Art von Fehler. In einem Testprozess wurde eine Zugriffsverletzung beim Ausführen eines HeapFree-E0E0E0E0 festgestellt. Es stellte sich heraus, dass der Test eine -Struktur zugeordnet, sie nicht ordnungsgemäß initialisiert und dann den Destruktor des Objekts aufgerufen hat. Da ein bestimmtes Feld nicht NULL war (es hatte E0E0E0E0 darin), hat es delete aufgerufen.

Technische Details zum Seitenheap

Um Heapbeschädigungen (Überläufe oder Unterläufe) zu erkennen, ändert AppVerifier die Speicherbelegung, indem der angeforderte Arbeitsspeicher entweder mit vollständigen nicht beschreibbaren Seiten oder mit speziellen Tags vor und nach dem zugeordneten Arbeitsspeicher aufgefüllt wird. Dazu lädt AppVerifier Verifier.dll in den überprüften Prozess und leitet einige der von der Anwendung aufgerufenen Win32-Heap-APIs an die entsprechenden Verifier.dll-APIs um.

Beim Auffüllen des angeforderten Arbeitsspeichers mit vollständigen nicht beschreibbaren Seiten (die Einstellung FULL ist im Abschnitt mit den Seitenheapeigenschaften aktiviert und ist die Standardeinstellung), verbraucht AppVerifier eine große Menge an virtuellem Arbeitsspeicher, hat jedoch den Vorteil, dass Heapbeschädigungsereignisse in Echtzeit zwischengespeichert werden, wenn der Überlauf oder Unterlauf auftritt. Denken Sie daran, dass der Arbeitsspeicher in diesem Modus entweder wie folgt aussieht [AppVerifier Read-Only Heap page (4k)] [Menge des von der zu test stehenden Anwendung angeforderten Arbeitsspeichers] oder wie folgt [Menge des von der getesteten Anwendung angeforderten Arbeitsspeichers] [AppVerifier Read-Only Heap page (4k)].

Bei der Heapprüfung wird eine Wächterseite am Anfang oder Ende der Zuordnung platziert, abhängig von der Backward-Eigenschaft. Wenn Rückwärts auf False festgelegt ist, was die Standardeinstellung ist, wird eine Schutzseite am Ende der Zuordnung platziert, um Pufferüberläufe abzufangen. Wenn sie auf True festgelegt ist, wird die Schutzseite am Anfang der Zuordnung platziert, um Pufferunterläufe abzufangen.

Beim Auffüllen des angeforderten Arbeitsspeichers mit speziellen Tags (aktiviert durch Deaktivieren des Kontrollkästchenelements "Vollständig" in den Heapeigenschaften), überprüft AppVerifier und benachrichtigt Sie, wenn dieser Speicher freigegeben wird. Das Standard Problem bei der Verwendung dieser Technik besteht darin, dass es einige Fälle gibt, in denen die Speicherbeschädigung erst erkannt wird, wenn der Arbeitsspeicher freigegeben wird (die Mindestmenge des Arbeitsspeicherblocks beträgt 8 Byte). Wenn also eine 3-Byte-Variable oder ein 5-Byte-Überlauf auftritt, wird er nicht sofort erkannt.

Bei einem Unterlaufereignis wird versucht, in eine Read-Only Seite zu schreiben. Dadurch wird eine Ausnahme ausgelöst. Beachten Sie, dass diese Ausnahme nur abgefangen werden kann, wenn die Zielanwendung unter einem Debugger ausgeführt wird. Beachten Sie, dass der Ganzseitenheapmodus diese Fehler ebenfalls erkennt, da er Auffüllen+Schützen von Seiten verwendet. Der Grund, warum Sie den hellen Seitenheap verwenden würden, ist, wenn Ihr Computer die hohen Speichereinschränkungen des Ganzseitenheaps nicht tolerieren kann.

Bei speicherintensiven Anwendungen oder wenn AppVerifier während langer Zeiträume (z. B. Belastungstests) verwendet werden muss, ist es aufgrund der Leistungsbeeinträchtigung besser, normale (leichte) Heaptests statt im Vollmodus auszuführen. Wenn jedoch ein Problem vorliegt, aktivieren Sie den ganzseitigen Heap, um dies weiter zu untersuchen.

Anwendungen, die benutzerdefinierte Heaps verwenden (ein Heap, der die Implementierung des Heaps des Betriebssystems umgeht), können möglicherweise nicht den vollen Vorteil der Verwendung von Seitenheaps nutzen oder sogar fehlfunktionieren, wenn er aktiviert ist.

Debuggen von Arbeitsspeicherfehlern

Die Speicherüberprüfungsdebuggererweiterung

Im Vorgangsprotokoll für virtuelle Räume werden alle Routinen nachverfolgt, die den virtuellen Bereich eines Prozesses in beliebiger Weise ändern. Dazu gehören VirtualAlloc, VirtualFree, MapViewOfFile und UnmapViewOfFile.

Sie können den Erweiterungsbefehl !avrf -vs Length verwenden, um die letzten Datensätze anzuzeigen. Length gibt die Anzahl der Datensätze an.

Sie können !avrf -vs -a Address verwenden, um alle Vorgänge des virtuellen Raums anzuzeigen, die sich auf die angegebene Adresse auswirken. Für eine Zuordnung reicht es aus, dass Die Adresse im zugeordneten Block enthalten ist. Für einen kostenlosen muss die genaue Adresse des Anfangs der Region angegeben werden.

Für jeden Eintrag im Protokoll werden die folgenden Informationen angezeigt:

  • Die -Funktion mit dem Namen
  • Die Thread-ID des Threads, der die Routine aufgerufen hat.
  • Die Adresse, die am Anruf beteiligt ist – dies ist die Adresse, die von einer Zuordnungsroutine zurückgegeben oder an eine freie Routine übergeben wurde.
  • Die Größe der Region, die am Anruf beteiligt ist
  • Der Typ des Arbeitsspeichervorgangs (der AllocationType-Parameter)
  • Der Typ des angeforderten Schutzes
  • Die Stapelüberwachung des Aufrufs

Beispiele

Die neuesten Einträge werden zuerst angezeigt.

Im folgenden Beispiel werden die beiden letzten Einträge angezeigt:

0:001> !avrf -vs 2

VirtualFree (tid: 0xB4): addr:04bb0000 sz:00400000 op:8000 prot:0
        00aa1ac2: verifier!VsLogCall+0x42
        00aa19c1: verifier!AVrfpNtFreeVirtualMemory+0x30
        68925d17: kernel32!VirtualFreeEx+0x35
        6892611c: kernel32!VirtualFree+0x13
        75ef6525: mshtml+0x116525
        75ef68af: mshtml+0x1168AF
        6a20787c: ntdll!LdrpCallInitRoutine+0x14
        6a211c6f: ntdll!LdrUnloadDll+0x39A
        689275c1: kernel32!FreeLibrary+0x3B
        77b22d69: ole32!CoQueryReleaseObject+0x1E6
        77b02bd2: ole32!SetErrorInfo+0x1ED

VirtualFree (tid: 0xB4): addr:04bb0000 sz:00001000 op:4000 prot:0

        00aa1ac2: verifier!VsLogCall+0x42
        00aa19c1: verifier!AVrfpNtFreeVirtualMemory+0x30
        68925d17: kernel32!VirtualFreeEx+0x35
        6892611c: kernel32!VirtualFree+0x13
        75ef65ae: mshtml+0x1165AE
        75ef68af: mshtml+0x1168AF
        6a20787c: ntdll!LdrpCallInitRoutine+0x14
        6a211c6f: ntdll!LdrUnloadDll+0x39A
        689275c1: kernel32!FreeLibrary+0x3B
        77b22d69: ole32!CoQueryReleaseObject+0x1E6
        77b02bd2: ole32!SetErrorInfo+0x1ED

Es ist in der Ausgabe ersichtlich, dass thread 0xB4 zuerst eine Seite freigegeben und dann den gesamten virtuellen Bereich freigegeben hat.

Hier sehen Sie eine Anzeige aller Vorgänge, die sich auf die Adresse 0x4BB1000 auswirken:

0:001> !avrf -vs -a 4bb1000

Searching in vspace log for address 04bb1000 ...

VirtualFree (tid: 0xB4): addr:04bb0000 sz:00400000 op:8000 prot:0
        00aa1ac2: verifier!VsLogCall+0x42
        00aa19c1: verifier!AVrfpNtFreeVirtualMemory+0x30
        68925d17: kernel32!VirtualFreeEx+0x35
        6892611c: kernel32!VirtualFree+0x13
        75ef6525: mshtml+0x116525
        75ef68af: mshtml+0x1168AF
        6a20787c: ntdll!LdrpCallInitRoutine+0x14
        6a211c6f: ntdll!LdrUnloadDll+0x39A
        689275c1: kernel32!FreeLibrary+0x3B
        77b22d69: ole32!CoQueryReleaseObject+0x1E6
        77b02bd2: ole32!SetErrorInfo+0x1ED

VirtualFree (tid: 0xB4): addr:04bb1000 sz:00001000 op:4000 prot:0

        00aa1ac2: verifier!VsLogCall+0x42
        00aa19c1: verifier!AVrfpNtFreeVirtualMemory+0x30
        68925d17: kernel32!VirtualFreeEx+0x35
        6892611c: kernel32!VirtualFree+0x13
        75ef65ae: mshtml+0x1165AE
        75ef68af: mshtml+0x1168AF
        6a20787c: ntdll!LdrpCallInitRoutine+0x14
        6a211c6f: ntdll!LdrUnloadDll+0x39A
        689275c1: kernel32!FreeLibrary+0x3B
        77b22d69: ole32!CoQueryReleaseObject+0x1E6
        77b02bd2: ole32!SetErrorInfo+0x1ED

VirtualAlloc (tid: 0xB4): addr:04bb0000 sz:00010000 op:1000 prot:4

        00aa1ac2: verifier!VsLogCall+0x42
        00aa1988: verifier!AVrfpNtAllocateVirtualMemory+0x37
        68925ca3: kernel32!VirtualAllocEx+0x61
        68926105: kernel32!VirtualAlloc+0x16
        75ef63f3: mshtml+0x1163F3

VirtualAlloc (tid: 0xB4): addr:04bb0000 sz:00400000 op:2000 prot:4

        00aa1ac2: verifier!VsLogCall+0x42
        00aa1988: verifier!AVrfpNtAllocateVirtualMemory+0x37
        68925ca3: kernel32!VirtualAllocEx+0x61
        68926105: kernel32!VirtualAlloc+0x16
        75ef63d9: mshtml+0x1163D9

Wenn Sie diese Ausgabe lesen möchten, denken Sie daran, dass die Einträge beginnend mit dem neuesten gespeichert werden. Daher zeigt dieses Protokoll, dass thread 0xB4 einem großen Bereich zugeordnet, in dem ein Commit für eine Seite ausgeführt wurde. Später wurde die Seite freigegeben und dann die gesamte virtuelle Region freigegeben.

Weitere Informationen

Application Verifier – Übersicht

Application Verifier – Testen von Anwendungen

Application Verifier – Tests in Application Verifier

Application Verifier – Stoppcodes und Definitionen

Application Verifier – Häufig gestellte Fragen