Share via


Schreiben eines Ausnahmefilters

Sie können eine Ausnahme behandeln, indem Sie entweder auf die Ebene des Ausnahmehandlers wechseln oder die Ausführung fortsetzen. Anstatt den Ausnahmehandlercode zum Behandeln der Ausnahme und zum Durchfallen zu verwenden, können Sie einen Filterausdruck verwenden, um das Problem zu sauber. Wenn Sie dann (-1) zurückgeben EXCEPTION_CONTINUE_EXECUTION , können Sie den normalen Fluss fortsetzen, ohne den Stapel zu löschen.

Hinweis

Einige Ausnahmen können nicht fortgesetzt werden. Wenn der Filter für eine solche Ausnahme als -1 ausgewertet wird, löst das System eine neue Ausnahme aus. Beim Aufrufen RaiseExceptionbestimmen Sie, ob die Ausnahme fortgesetzt wird.

Der folgende Code verwendet beispielsweise einen Funktionsaufruf im Filterausdruck : Diese Funktion behandelt das Problem und gibt dann -1 zurück, um den normalen Kontrollfluss fortzusetzen:

// exceptions_Writing_an_Exception_Filter.cpp
#include <windows.h>
int main() {
   int Eval_Exception( int );

   __try {}

   __except ( Eval_Exception( GetExceptionCode( ))) {
      ;
   }

}
void ResetVars( int ) {}
int Eval_Exception ( int n_except ) {
   if ( n_except != STATUS_INTEGER_OVERFLOW &&
      n_except != STATUS_FLOAT_OVERFLOW )   // Pass on most exceptions
   return EXCEPTION_CONTINUE_SEARCH;

   // Execute some code to clean up problem
   ResetVars( 0 );   // initializes data to 0
   return EXCEPTION_CONTINUE_EXECUTION;
}

Es ist ratsam, einen Funktionsaufruf im Filterausdruck zu verwenden, wenn der Filter etwas Komplexes ausführen muss. Das Auswerten des Ausdrucks verursacht die Ausführung der Funktion, in diesem Fall Eval_Exception.

Beachten Sie die Verwendung der GetExceptionCode Ausnahme. Diese Funktion muss innerhalb des Filterausdrucks der __except Anweisung aufgerufen werden. Eval_Exception kann nicht aufgerufen GetExceptionCodewerden, aber es muss der Ausnahmecode an ihn übergeben werden.

Dieser Handler übergibt die Steuerung an einen anderen Handler, sofern die Ausnahme keine Ganzzahl oder ein Gleitkommaüberlauf ist. Wenn dies der Fall ist, ruft der Handler eine Funktion (ResetVars ist nur ein Beispiel, keine API-Funktion) auf, um mehrere globale Variablen zurückzusetzen. Der __except Anweisungsblock, der in diesem Beispiel leer ist, kann nie ausgeführt werden, weil Eval_Exception nie (1) zurückgegeben EXCEPTION_EXECUTE_HANDLER wird.

Die Verwendung eines Funktionsaufrufs ist ein gutes allgemeines Verfahren für die Behandlung von komplexen Filterausdrücken. Zwei andere hilfreiche Funktionen der Programmiersprache C sind:

  • Der bedingte Operator

  • Der Kommaoperator

Der bedingte Operator ist hier häufig hilfreich. Es kann verwendet werden, um nach einem bestimmten Rückgabecode zu suchen und dann einen von zwei verschiedenen Werten zurückzugeben. Beispielsweise erkennt der Filter im folgenden Code die Ausnahme nur, wenn die Ausnahme lautet STATUS_INTEGER_OVERFLOW:

__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ? 1 : 0 ) {

Der bedingte Operator ist in diesem Fall in erster Linie dafür verantwortlich, Klarheit zu schaffen, da der folgende Code zum gleichen Ergebnis führt:

__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ) {

Der bedingte Operator ist in Situationen nützlicher, in denen der Filter in -1 EXCEPTION_CONTINUE_EXECUTIONausgewertet werden soll.

Mit dem Kommaoperator können Sie mehrere Ausdrücke in Sequenz ausführen. Anschließend wird der Wert des letzten Ausdrucks zurückgegeben. Der folgenden Code speichert z. B. den Ausnahmecode in einer Variablen und testet dann auf:

__except( nCode = GetExceptionCode(), nCode == STATUS_INTEGER_OVERFLOW )

Siehe auch

Schreiben eines Ausnahmehandlers
Structured Exception Handling (C/C++)