Filtern von strukturierten Exceptions (C++)
Nach oben zu Strukturierte Exceptions unter Win32 (C++)
Ein Filterausdruck kann eine Filterfunktion aufrufen, aber die Filterfunktion kann GetExceptionInformation nicht aufrufen. Sie können den Rückgabewert von GetExceptionInformation als Parameter an die Filterfunktion übergeben.
Für die Übergabe der EXCEPTION_POINTERS-Information an eine Exception-Behandlungsroutine muss der Filterausdruck oder die Filterfunktion den Zeiger oder die Daten aus GetExceptionInformation an eine Position kopieren, auf die die Behandlungsroutine später zugreifen kann.
Bei verschachtelten try-except-Anweisungen wird jeder Filterausdruck der Anweisung ausgewertet, bis EXCEPTION_EXECUTE_HANDLER oder EXCEPTION_CONTINUE_EXECUTION gefunden wird. Ein Filterausdruck kann zum Ermitteln von Exception-Informationen GetExceptionInformation aufrufen.
Wenn GetExceptionInformation oder GetExceptionCode direkt von dem für __except bereitgestellten Ausdruck aufgerufen wird, können Sie mit einer Funktion festlegen, was mit einer Exception geschehen soll, anstatt einen komplexen C++-Ausdruck zu erstellen. Fast die gesamten für die Behandlung einer Exception erforderlichen Informationen können aus dem Ergebnis von GetExceptionInformation extrahiert werden. GetExceptionInformation gibt einen Zeiger auf eine EXCEPTION_POINTERS-Struktur zurück:
struct EXCEPTION_POINTERS {
EXCEPTION_RECORD *ExceptionRecord;
CONTEXT *Context;
};
EXCEPTION_RECORD enthält den rechnerunabhängigen Status:
struct EXCEPTION_RECORD {
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct EXCEPTION_RECORD *ExceptionRecord;
void *ExceptionAddress;
DWORD NumberParameters;
DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
};
Normalerweise legt die Filterfunktion auf Basis der Informationen in dem ExceptionRecord ihre Reaktion fest. Manchmal werden spezifischere Informationen benötigt (insbesondere, wenn die Aktion EXCEPTION_CONTINUE_EXECUTION ausgeführt werden soll: wenn nichts vorgesehen ist, würde der Code, der die Exception verursacht hat, erneut ausgeführt). Für diese Situationen stellt das andere Feld der EXCEPTION_POINTERS-Struktur den Prozessorstatus zum Zeitpunkt des Auftretens der Exception bereit. Wenn diese Struktur geändert wird, und der Filter EXCEPTION_CONTINUE_EXCEPTION zurückgibt, wird damit vor dem Fortsetzen der Ausführung der Status des Thread gesetzt. Zum Beispiel:
static int xfilter(EXCEPTION_POINTERS *xp) {
int rc;
EXCEPTION_RECORD *xr = xp->ExceptionRecord;
CONTEXT *xc = xp->Context;
switch (xr->ExceptionCode) {
case EXCEPTION_BREAKPOINT:
// whoops, someone left an embedded breakpoint.
// just step over it (1 byte on x86)
++xc->Eip;
rc = EXCEPTION_CONTINUE_EXECUTION;
break;
case EXCEPTION_ACCESS_VIOLATION:
rc = EXCEPTION_EXECUTE_HANDLER;
break;
default:
// give up
rc = EXCEPTION_CONTINUE_SEARCH;
break;
};
return rc;
}
// ...
EXCEPTION_POINTERS * xp;
try {
func();
}
__except (xfilter(xp = GetExceptionInformation())) {
abort();
}