try-except Prohlášení

Tento try-except příkaz je rozšíření specifické pro Microsoft, které podporuje strukturované zpracování výjimek v jazycích C a C++.

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

Gramatika

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

Poznámky

Tento try-except příkaz je rozšířením Microsoftu pro jazyky C a C++. Umožňuje cílovým aplikacím získat kontrolu nad událostmi, které obvykle ukončují provádění programu. Tyto události se označují jako strukturované výjimky nebo výjimky pro krátkou dobu. Mechanismus, který se těmito výjimkami zabývá, se nazývá strukturované zpracování výjimek (SEH).

Související informace najdete v příkazu try-finally.

Výjimky můžou být hardwarové nebo softwarové. Strukturované zpracování výjimek je užitečné i v případě, že se aplikace nemůžou úplně zotavit z výjimek hardwaru nebo softwaru. SEH umožňuje zobrazit informace o chybách a zachytit vnitřní stav aplikace, který pomáhá diagnostikovat problém. Je zvlášť užitečná pro občasné problémy, které se nesnadně reprodukují.

Poznámka

Strukturované zpracování výjimek funguje na architektuře Win32 pro zdrojové soubory jazyka C i C++. Není ale speciálně určená pro jazyk C++. Větší přenositelnost kódu lze zajistit použitím zpracování výjimek jazyka C++. Zpracování výjimek jazyka C++ je také více flexibilní, jelikož dokáže zpracovat výjimky libovolného typu. Pro programy C++ doporučujeme použít nativní zpracování výjimek jazyka C++: try, catch a throw příkazy.

Složený příkaz za klauzulí __try je tělo nebo strážený oddíl. Výraz __except se také označuje jako výraz filtru . Jeho hodnota určuje způsob zpracování výjimky. Složený příkaz po klauzuli __except je obslužnou rutinou výjimky. Obslužná rutina určuje akce, které se mají provést, pokud je při provádění oddílu těla vyvolána výjimka. Provádění pokračuje následujícím způsobem:

  1. Chráněná část je spuštěna.

  2. Nedojde-li za běhu chráněné části k žádné výjimce, pokračuje běh programu příkazem za klauzulí __except.

  3. Pokud během provádění strážené části nebo v jakékoli rutině volání strážených oddílů dojde k výjimce, __except výraz se vyhodnotí. Existují tři možné hodnoty:

    • EXCEPTION_CONTINUE_EXECUTION (-1) Výjimka je zamítnuta. Program bude pokračovat tam, kde k výjimce došlo.

    • EXCEPTION_CONTINUE_SEARCH (0) Výjimka není rozpoznána. Pokračujte ve vyhledávání zásobníku pro obslužnou rutinu, nejprve pro obsahující try-except příkazy a potom pro obslužné rutiny s další nejvyšší prioritou.

    • EXCEPTION_EXECUTE_HANDLER (1) Je rozpoznána výjimka. Přeneste řízení do obslužné rutiny výjimky spuštěním složeného __except příkazu a pak pokračujte ve spuštění za blokem __except .

Výraz __except se vyhodnotí jako výraz jazyka C. Je omezena na jednu hodnotu, operátor podmíněného výrazu nebo operátor čárky. Je-li požadováno rozsáhlejší zpracování, může výraz zavolat rutinu, která vrátí jednu z výše uvedených tří hodnot.

Každá aplikace může obsahovat svou vlastní obslužnou rutinu výjimky.

Není platné přejít na __try příkaz, ale je platný přeskočit z jednoho příkazu. Obslužná rutina výjimky není volána, pokud je proces ukončen uprostřed provádění try-except příkazu.

Z důvodu kompatibility s předchozími verzemi jsou _try, _except a _leave synonyma pro __try, __excepta __leave pokud není zadána možnost kompilátoru /Za (Zakázat jazyková rozšíření).

Klíčové __leave slovo

Klíčové __leave slovo je platné pouze v rámci strážené části try-except příkazu a jeho účinkem je přeskočit na konec strážené části. Běh programu pokračuje prvním příkazem za obslužnou rutinou výjimky.

Příkaz goto může také vyskočit z strážené části a nezhorší výkon, jak to dělá v příkazu try-finally . Důvodem je to, že k odvíjení zásobníku nedojde. Doporučujeme ale místo příkazu použít __leave klíčové slovo goto . Důvodem je to, že méně pravděpodobné je, že uděláte chybu programování, pokud je strážený oddíl velký nebo složitý.

Vnitřní funkce strukturovaného zpracování výjimek

Strukturované zpracování výjimek poskytuje dvě vnitřní funkce, které jsou k dispozici pro použití s příkazem try-except : GetExceptionCode a GetExceptionInformation.

GetExceptionCode vrátí kód (32bitové celé číslo) výjimky.

Vnitřní funkce GetExceptionInformation vrátí ukazatel na strukturu EXCEPTION_POINTERS obsahující další informace o výjimce. Pomocí tohoto ukazatele lze přistoupit ke stavu počítače, v jakém byl v době výskytu hardwarové výjimky. Struktura je následující:

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

Typy PEXCEPTION_RECORD ukazatelů a PCONTEXT jsou definovány v souboru include <winnt.h> a _EXCEPTION_RECORD_CONTEXT jsou definovány v souboru include <excpt.h.>

Můžete použít GetExceptionCode v rámci obslužné rutiny výjimky. Můžete však použít GetExceptionInformation pouze ve výrazu filtru výjimek. Informace, na které odkazuje, jsou obecně v zásobníku a už nejsou k dispozici, když se ovládací prvek přenese do obslužné rutiny výjimky.

Vnitřní funkce AbnormalTermination je k dispozici v obslužné rutině ukončení. Vrátí hodnotu 0, pokud se text příkazu try-finally postupně ukončí. Ve všech ostatních případech vrátí hodnotu 1.

<excpt.h> definuje některé alternativní názvy těchto vnitřních objektů:

GetExceptionCode je ekvivalentní _exception_code

GetExceptionInformation je ekvivalentní _exception_info

AbnormalTermination je ekvivalentní _abnormal_termination

Příklad

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

Výstup

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

Viz také

Zápis obslužné rutiny výjimky
Strukturované zpracování výjimek (C/C++)
Klíčová slova