try-except-Anweisung

Die try-except Anweisung ist eine microsoftspezifische Erweiterung, die die strukturierte Ausnahmebehandlung in den Sprachen 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 Sprachen C und C++. Es ermöglicht Zielanwendungen die Kontrolle zu erlangen, wenn Ereignisse auftreten, die die Programmausführung normalerweise beenden. Solche Ereignisse werden kurz als strukturierte Ausnahmen oder Ausnahmen bezeichnet. Der Mechanismus, der sich mit diesen Ausnahmen befasst, wird als strukturierte Ausnahmebehandlung (SEH) bezeichnet.

Verwandte Informationen finden Sie in der try-finally-Anweisung.

Ausnahmen können entweder hardwarebasiert oder softwarebasiert sein. Die strukturierte Ausnahmebehandlung ist nützlich, auch wenn Anwendungen nicht vollständig von Hardware- oder Softwareausnahmen wiederherstellen können. SEH ermöglicht es, Fehlerinformationen anzuzeigen und den internen Zustand der Anwendung abzufangen, um das Problem zu diagnostizieren. Es ist besonders nützlich für zeitweilige Probleme, die nicht leicht zu reproduzieren sind.

Hinweis

Die strukturierte Ausnahmebehandlung arbeitet mit Win32 für C- und C++-Quelldateien. Es wurde jedoch nicht speziell für C++ entwickelt. 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 empfohlen, systemeigene C++-Ausnahmebehandlung zu verwenden: try, catch, and throw statements.

Die zusammengesetzte Anweisung nach der __try Klausel ist der Textkörper oder der geschützte Abschnitt. Der __except Ausdruck wird auch als Filterausdruck bezeichnet. Der Wert bestimmt, wie die Ausnahme behandelt wird. Die Verbundanweisung nach der __except-Klausel ist der Ausnahmehandler. Der Handler gibt die auszuführenden Aktionen an, 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 eine Ausnahme während der Ausführung des geschützten Abschnitts oder in einer Routine der geschützten Abschnittsaufrufe auftritt, wird der __except Ausdruck ausgewertet. Es gibt drei mögliche Werte:

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

    • EXCEPTION_CONTINUE_SEARCH (0) Ausnahme wird 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 wird erkannt. Übertragen Sie das Steuerelement an den Ausnahmehandler, indem Sie die __except Verbund-Anweisung ausführen und dann die Ausführung nach dem __except Block fortsetzen.

Der __except Ausdruck wird als C-Ausdruck ausgewertet. Er ist auf einen einzelnen Wert, den Operator für bedingten Ausdruck 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 gültig, in eine __try Anweisung zu springen, aber gültig, um aus einer zu springen. Der Ausnahmehandler wird nicht aufgerufen, wenn ein Prozess in der Mitte der Ausführung einer try-except Anweisung beendet wird.

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

dem __leave-Schlüsselwort

Die __leave Schlüsselwort (keyword) ist nur innerhalb des geschützten Abschnitts einer try-except Anweisung gültig, und der Effekt besteht darin, zum Ende des geschützten Abschnitts zu springen. Die Ausführung wird mit der ersten Anweisung nach dem Ausnahmehandler fortgesetzt.

Eine goto Anweisung kann auch aus dem geschützten Abschnitt springen und beeinträchtigt die Leistung nicht wie in einer try-finally-Anweisung . Das liegt daran, dass die Stapelentspannung nicht auftritt. Es wird jedoch empfohlen, die __leave Schlüsselwort (keyword) anstelle einer goto Anweisung zu verwenden. Der Grund dafür ist, dass Sie weniger wahrscheinlich einen Programmierfehler machen, wenn der geschützte Abschnitt groß oder komplex ist.

Strukturierte Ausnahmebehandlung systeminterner Funktionen

Die strukturierte Ausnahmebehandlung bietet zwei systeminterne Funktionen, die für die Verwendung mit der try-except Anweisung verfügbar sind: 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 Informationen zur 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 werden in der include-Datei <winnt.h> definiert und _EXCEPTION_RECORD in der include file <excpt.h definiert._CONTEXT>

Sie können innerhalb des Ausnahmehandlers verwenden GetExceptionCode . Sie können jedoch nur innerhalb des Ausnahmefilterausdrucks verwenden GetExceptionInformation . Die Informationen, auf die sie verweist, befinden sich im Allgemeinen im Stapel und sind nicht mehr verfügbar, wenn das Steuerelement an den Ausnahmehandler übertragen wird.

Die systeminterne Funktion AbnormalTermination ist in einem Beendigungshandler verfügbar. Er gibt 0 zurück, wenn der Textkörper der try-finally-Anweisung sequenziell beendet wird. In allen anderen Fällen wird 1 zurückgegeben.

<excpt.h> definiert einige alternative Namen für diese systeminternen Elemente:

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

Ausgabe

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

Siehe auch

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