Behandeln von Ausnahmen
Das Betriebssystem verwendet die strukturierte Ausnahmebehandlung, um bestimmte Arten von Fehlern zu signalisieren. Eine routine, die von einem Treiber aufgerufen wird, kann eine Ausnahme auslösen, die der Treiber behandeln muss.
Das System fängt die folgenden allgemeinen Arten von Ausnahmen ab:
Hardwaredefinierte Fehler oder Fallen, z. B.
- Zugriffsverletzungen (siehe unten)
- Datentypfehler (z. B. eine 16-Bit-Entität, die an einer Odd-Byte-Grenze ausgerichtet ist)
- Illegale und privilegierte Anweisungen
- Ungültige Sperrsequenzen (Versuch, eine ungültige Sequenz von Anweisungen in einem ineinander verriegelten Codeabschnitt auszuführen)
- Ganzzahlige Teilungen durch Null und Überläufe
- Gleitkommateilungen durch Null, Überläufe, Unterläufe und reservierte Operanden
- Haltepunkte und Einzelschrittausführung (zur Unterstützung von Debuggern)
Systemsoftwaredefinierte Ausnahmen, z. B.
- Verletzungen der Schutzseite (Versuch, Daten von oder an einem Speicherort innerhalb einer Schutzseite zu laden oder zu speichern)
- Fehler beim Lesen von Seiten (Beim Versuch, eine Seite in den Arbeitsspeicher zu lesen, und es tritt ein gleichzeitiger E/A-Fehler auf)
Eine Zugriffsverletzung ist ein Versuch, einen Vorgang auf einer Seite auszuführen, die unter den aktuellen Seitenschutzeinstellungen nicht zulässig ist. Zugriffsverletzungen treten in den folgenden Situationen auf:
Ein ungültiger Lese- oder Schreibvorgang, z. B. das Schreiben auf eine schreibgeschützte Seite.
Zugriff auf Arbeitsspeicher, der über die Grenzen des Adressraums des aktuellen Programms hinausgeht (als Längenverletzung bezeichnet).
Um auf eine Seite zuzugreifen, die sich derzeit befindet, aber der Verwendung einer Systemkomponente gewidmet ist. Beispielsweise darf Code im Benutzermodus nicht auf eine Seite zugreifen, die vom Kernel verwendet wird.
Wenn ein Vorgang eine Ausnahme verursachen kann, sollte der Treiber den Vorgang in einen Try/Except-Block einschließen. Zugriffe auf Standorte im Benutzermodus sind typische Ursachen für Ausnahmen. Beispielsweise überprüft die ProbeForWrite-Routine , ob der Treiber tatsächlich in einen Benutzermoduspuffer schreiben kann. Wenn dies nicht möglich ist, löst die Routine eine STATUS_ACCESS_VIOLATION Ausnahme aus. Im folgenden Codebeispiel ruft der Treiber ProbeForWrite in einem try/except auf, damit er die resultierende Ausnahme behandeln kann, falls eine auftreten sollte.
try {
...
ProbeForWrite(Buffer, BufferSize, BufferAlignment);
/* Note that any access (not just the probe, which must come first,
* by the way) to Buffer must also be within a try-except.
*/
...
} except (EXCEPTION_EXECUTE_HANDLER) {
/* Error handling code */
...
}
Treiber müssen alle ausgelösten Ausnahmen behandeln. Eine Ausnahme, die nicht behandelt wird, führt zu einer Fehlerüberprüfung des Systems. Der Treiber, der bewirkt, dass die Ausnahme ausgelöst wird, muss sie behandeln: Ein Treiber auf niedrigerer Ebene kann sich nicht auf einen Treiber auf höherer Ebene verlassen, um die Ausnahme zu behandeln.
Treiber können eine Ausnahme direkt auslösen, indem sie die Routinen ExRaiseAccessViolation, ExRaiseDatatypeMisalignment oder ExRaiseStatus verwenden. Der Treiber muss alle Ausnahmen behandeln, die diese Routinen auslösen.
Im Folgenden finden Sie eine teilweise Liste von Routinen, die zumindest in bestimmten Situationen eine Ausnahme auslösen können:
Speicherzugriffe auf Puffer im Benutzermodus können auch Zugriffsverletzungen verursachen. Weitere Informationen finden Sie unter Fehler beim Verweisen auf User-Space Adressen.
Beachten Sie, dass sich die strukturierte Ausnahmebehandlung von C++-Ausnahmen unterscheidet. C++-Ausnahmen werden vom Kernel nicht unterstützt.
Weitere Informationen zur strukturierten Ausnahmebehandlung finden Sie in der Microsoft Windows SDK und in der Visual Studio-Dokumentation.