Freigeben über


try-except-Anweisung

Die try-except-Anweisung ist eine Microsoft-spezifische Erweiterung, die die strukturierte Ausnahmebehandlung in den Programmiersprachen C und C++ unterstützt.

    // . . .
    __try {
        // guarded code
    }
    __except ( /* filter expression */ ) {
        // termination code
    }
    // . . .

Grammatik

try-except-statement:
__try compound-statement __except ( expression ) compound-statement

Hinweise

Die try-except-Anweisung ist eine Microsoft-Erweiterung für die Programmiersprachen C und C++. Sie ermöglicht es Zielanwendungen, die Steuerung zu übernehmen, wenn Ereignisse auftreten, die normalerweise die Programmausführung beenden. Solche Ereignisse werden strukturierte Ausnahmen oder kurz Ausnahmen genannt. Der Mechanismus, der diese Ausnahmen behandelt, wird als strukturierte Ausnahmebehandlung (Structured Exception Handling, SEH) bezeichnet.

Weitere Informationen finden Sie unter der try-finally-Anweisung.

Ausnahmen können hardware- oder softwarebasiert sein. Die strukturierte Ausnahmebehandlung ist auch dann hilfreich, wenn Anwendungen nach Hardware- oder Softwareausnahmen möglicherweise nicht vollständig wiederhergestellt werden können. SEH ermöglicht das Anzeigen von Fehlerinformationen und die Erfassung des internen Zustands der Anwendung, um das Problem besser diagnostizieren zu können. Das ist besonders hilfreich bei vorübergehend auftretenden Problemen, die sich nicht ohne Weiteres reproduzieren lassen.

Hinweis

Die strukturierte Ausnahmebehandlung arbeitet mit Win32 für C- und C++-Quelldateien. SEH ist jedoch nicht speziell für C++ konzipiert. Sie können sicherstellen, dass der Code portabler ist, indem Sie die C++-Ausnahmebehandlung verwenden. Die C++-Ausnahmebehandlung ist auch flexibler, da sie Ausnahmen eines beliebigen Typs behandeln kann. Für C++-Programme wird die Verwendung der nativen C++-Ausnahmebehandlung in Form von try-, catch- und throw-Anweisungen empfohlen.

Die Verbundanweisung nach der __try-Klausel ist der Textabschnitt bzw. der geschützte Abschnitt. Der __except-Ausdruck wird auch als Filterausdruck bezeichnet. Sein Wert bestimmt, wie die Ausnahme behandelt wird. Die Verbundanweisung nach der __except-Klausel ist der Ausnahmehandler. Der Handler gibt die Aktionen an, die ausgeführt werden sollen, wenn während der Ausführung des Textabschnitts eine Ausnahme ausgelöst wird. Die Ausführung erfolgt folgendermaßen:

  1. Der geschützte Bereich wird ausgeführt.

  2. Wenn keine Ausnahme während der Ausführung des geschützten Bereichs auftritt, wird die Ausführung mit der Anweisung nach der __except-Klausel fortgesetzt.

  3. Wenn während der Ausführung des geschützten Abschnitts oder in einer vom geschützten Abschnitt aufgerufenen Routine eine Ausnahme auftritt, wird der __except-Ausdruck ausgewertet. Es gibt drei mögliche Werte:

    • EXCEPTION_CONTINUE_EXECUTION (-1) Die Ausnahme wird geschlossen. Fortsetzen der Ausführung an der Stelle, an der die Ausnahme aufgetreten ist.

    • EXCEPTION_CONTINUE_SEARCH (0) Die Ausnahme wurde nicht erkannt. Fahren Sie fort, im Stapel nach einem Handler zu suchen, zuerst nach enthaltenen try-except-Anweisungen, dann nach Handlern mit der nächst höheren Priorität.

    • EXCEPTION_EXECUTE_HANDLER (1) Ausnahme wurde erkannt. Übertragen Sie die Steuerung auf den Ausnahmehandler, indem Sie die __except-Verbundanweisung ausführen, und setzen Sie dann die Ausführung nach dem __except-Block fort.

Der __except-Ausdruck wird als C-Ausdruck ausgewertet. Er ist auf einen einzelnen Wert, den bedingten Ausdrucksoperator oder den Kommaoperator beschränkt. Wenn eine erweiterte Verarbeitung erforderlich ist, kann der Ausdruck eine Routine aufrufen, die einen der drei Werte zurückgibt, die oben aufgelistet sind.

Jede Anwendung kann einen eigenen Ausnahmehandler haben.

Es ist nicht zulässig, in eine __try-Anweisung zu springen. Das Herausspringen aus einer solchen Anweisung ist dagegen zulässig. Der Ausnahmehandler wird nicht aufgerufen, wenn ein Prozess während der Ausführung einer try-except-Anweisung beendet wird.

Für die Kompatibilität mit früheren Versionen sind _try, _except und _leave Synonyme für __try, __except und __leave, es sei denn, die Compileroption /Za (Spracherweiterungen deaktivieren) wurde angegeben.

dem __leave-Schlüsselwort

Das __leave-Schlüsselwort ist nur im geschützten Abschnitt einer try-except-Anweisung gültig und führt zu einem Sprung zum Ende des geschützten Abschnitts. Die Ausführung wird mit der ersten Anweisung nach dem Ausnahmehandler fortgesetzt.

Eine goto-Anweisung kann auch aus dem geschützten Abschnitt herausspringen. Anders als bei einer try-finally-Anweisung wird dabei allerdings die Leistung nicht beeinträchtigt. Das liegt daran, dass keine Stapelentladung auftritt. Es wird jedoch empfohlen, keine goto-Anweisung, sondern das __leave-Schlüsselwort zu verwenden. Dadurch verringert sich die Wahrscheinlichkeit eines Programmierfehlers, wenn der geschützte Abschnitt groß oder komplex ist.

Systeminterne Funktionen der strukturierten Ausnahmebehandlung

Die strukturierte Ausnahmebehandlung bietet zwei systeminterne Funktionen, die mit der try-except-Anweisung verwendet werden können: GetExceptionCode und GetExceptionInformation.

GetExceptionCode gibt den Code (eine 32-Bit-Ganzzahl) der Ausnahme zurück.

Die systeminterne Funktion GetExceptionInformation gibt einen Zeiger auf eine EXCEPTION_POINTERS-Struktur zurück, die zusätzliche Information zu der Ausnahme enthält. Mit diesem Zeiger können Sie auf den Computerzustand zugreifen, der zum Zeitpunkt einer Hardwareausnahme vorhanden war. Die Struktur sieht wie folgt aus:

typedef struct _EXCEPTION_POINTERS {
    PEXCEPTION_RECORD ExceptionRecord;
    PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

Die Zeigertypen PEXCEPTION_RECORD und PCONTEXT sind in der Includedatei <winnt.h> definiert. _EXCEPTION_RECORD und _CONTEXT sind in der Includedatei <excpt.h> definiert.

Sie können GetExceptionCode innerhalb des Ausnahmehandlers verwenden. GetExceptionInformation kann allerdings nur innerhalb des Ausnahmefilterausdrucks verwendet werden. Die Information, auf die verwiesen wird, befindet sich im Allgemeinen im Stapel und ist nicht mehr verfügbar, wenn die Steuerung auf den Ausnahmehandler übergeht.

Die systeminterne Funktion AbnormalTermination steht innerhalb eines Beendigungshandlers zur Verfügung. Sie gibt „0“ zurück, wenn der Text der try-finally-Anweisung nacheinander beendet wird. In allen anderen Fällen wird 1 zurückgegeben.

<excpt.h> definiert mehrere alternative Namen für diese systeminternen Funktionen:

GetExceptionCode entspricht _exception_code

GetExceptionInformation entspricht _exception_info

AbnormalTermination entspricht _abnormal_termination

Beispiel

// exceptions_try_except_Statement.cpp
// Example of try-except and try-finally statements
#include <stdio.h>
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>

int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
    puts("in filter.");
    if (code == EXCEPTION_ACCESS_VIOLATION)
    {
        puts("caught AV as expected.");
        return EXCEPTION_EXECUTE_HANDLER;
    }
    else
    {
        puts("didn't catch AV, unexpected.");
        return EXCEPTION_CONTINUE_SEARCH;
    }
}

int main()
{
    int* p = 0x00000000;   // pointer to NULL
    puts("hello");
    __try
    {
        puts("in try");
        __try
        {
            puts("in try");
            *p = 13;    // causes an access violation exception;
        }
        __finally
        {
            puts("in finally. termination: ");
            puts(AbnormalTermination() ? "\tabnormal" : "\tnormal");
        }
    }
    __except(filter(GetExceptionCode(), GetExceptionInformation()))
    {
        puts("in except");
    }
    puts("world");
}

Output

hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
        abnormal
in except
world

Weitere Informationen

Schreiben eines Ausnahmehandlers
Structured Exception Handling (C/C++)
Schlüsselwörter