Filtern von strukturierten Exceptions (C++)

Aus RAD Studio
Wechseln zu: Navigation, Suche

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();
}

Siehe auch