Strukturované zpracování výjimek (C/C++)

Strukturované zpracování výjimek (SEH) je rozšíření Microsoftu pro C a C++ pro zpracování určitých výjimečných situací kódu, jako jsou hardwarové chyby, elegantně. Přestože systém Windows a Microsoft C++ podporují SEH, doporučujeme použít standardní zpracování výjimek C++ standardu ISO v kódu C++. Díky tomu je váš kód přenosnější a flexibilnější. Pokud ale chcete zachovat stávající kód nebo konkrétní druhy programů, možná budete muset použít SEH.

Specifické pro Microsoft:

Gramatika

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

try-finally-statement :
__try compound-statement __finally compound-statement

Poznámky

S SEH můžete zajistit správné uvolnění prostředků, jako jsou bloky paměti a soubory, pokud se neočekávaně ukončí provádění. Můžete také zpracovávat konkrétní problémy – například nedostatek paměti – pomocí stručného strukturovaného kódu, který nespoléhá na goto příkazy nebo propracované testování návratových kódů.

Příkazy try-except uvedené try-finally v tomto článku jsou rozšířeními jazyka C a C++ společnosti Microsoft. Podporují SEH tím, že aplikacím umožňují získat kontrolu nad programem po událostech, které by jinak ukončily provádění. I když SEH pracuje se zdrojovými soubory C++, není speciálně určen pro C++. Pokud používáte SEH v programu C++, který zkompilujete pomocí /EHa nebo /EHsc možnosti, jsou volány destruktory pro místní objekty, ale jiné chování provádění nemusí být to, co očekáváte. Obrázek najdete v příkladu dále v tomto článku. Ve většině případů místo SEH doporučujeme použít standardní zpracování výjimek C++standardu ISO. Pomocí zpracování výjimek jazyka C++ můžete zajistit, aby byl váš kód přenosnější a mohli zpracovat výjimky libovolného typu.

Pokud máte kód jazyka C, který používá SEH, můžete ho kombinovat s kódem C++, který používá zpracování výjimek jazyka C++. Informace naleznete v tématu Zpracování strukturovaných výjimek v jazyce C++.

Existují dva mechanismy SEH:

Tyto dva druhy obslužných rutin jsou odlišné, ale úzce souvisí s procesem známým jako odvíjení zásobníku. Když dojde ke strukturované výjimce, systém Windows vyhledá nedávno nainstalovanou obslužnou rutinu výjimky, která je aktuálně aktivní. Obslužná rutina může provádět jednu ze tří věcí:

  • Nepodařilo se rozpoznat výjimku a předat řízení jiným obslužné rutině (EXCEPTION_CONTINUE_SEARCH).

  • Rozpozná výjimku, ale zavře ji (EXCEPTION_CONTINUE_EXECUTION).

  • Rozpozná výjimku a zpracuje ji (EXCEPTION_EXECUTE_HANDLER).

Obslužná rutina výjimky, která rozpozná výjimku, nemusí být ve funkci, která byla spuštěna, když došlo k výjimce. Může být ve funkci mnohem vyšší v zásobníku. Aktuálně spuštěná funkce a všechny ostatní funkce v rámci zásobníku jsou ukončeny. Během tohoto procesu je zásobník unwound. To znamená, že místní nestatické proměnné ukončených funkcí se vymažou ze zásobníku.

Při odvíjení zásobníku operační systém volá všechny obslužné rutiny ukončení, které jste napsali pro každou funkci. Pomocí obslužné rutiny ukončení vyčistíte prostředky, které by jinak zůstaly otevřené kvůli neobvyklému ukončení. Pokud jste zadali kritický oddíl, můžete ho ukončit v obslužné rutině ukončení. Když se program vypne, můžete provádět další úlohy úklidu, jako je zavření a odebrání dočasných souborů.

Další kroky

Příklad

Jak bylo uvedeno dříve, destruktory pro místní objekty se volají, pokud v programu C++ použijete SEH a zkompilujete ho pomocí /EHa nebo /EHsc možnosti. Chování během provádění ale nemusí být to, co očekáváte, pokud používáte také výjimky jazyka C++. Tento příklad ukazuje tyto rozdíly v chování.

#include <stdio.h>
#include <Windows.h>
#include <exception>

class TestClass
{
public:
    ~TestClass()
    {
        printf("Destroying TestClass!\n");
    }
};

__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
    printf("Throwing C++ exception\n");
    throw std::exception("");
#else
    printf("Triggering SEH exception\n");
    volatile int *pInt = 0x00000000;
    *pInt = 20;
#endif
}

__declspec(noinline) void TestExceptions()
{
    TestClass d;
    TestCPPEX();
}

int main()
{
    __try
    {
        TestExceptions();
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        printf("Executing SEH __except block\n");
    }

    return 0;
}

Pokud používáte /EHsc ke kompilaci tohoto kódu, ale makro CPPEX místního testovacího ovládacího prvku není definováno, TestClass destruktor se nespustí. Výstup vypadá takto:

Triggering SEH exception
Executing SEH __except block

Pokud použijete /EHsc ke kompilaci kódu a CPPEX definujete ho pomocí /DCPPEX (aby se vyvolá výjimka jazyka C++), TestClass spustí se destruktor a výstup vypadá takto:

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

Pokud se používá /EHa ke kompilaci kódu, destruktor spustí, TestClass zda byla vyvolán výjimka pomocí standardního výrazu C++ throw nebo pomocí SEH. To znamená, jestli CPPEX je definován, nebo ne. Výstup vypadá takto:

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

Další informace najdete v tématu /EH (Model zpracování výjimek).

END Microsoft-specific

Viz také

Ošetření výjimek
Klíčová slova
<exception>
Zpracování chyb a výjimek
Strukturované zpracování výjimek (Windows)