Sdílet prostřednictvím


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

Ačkoli systém Windows i jazyk Visual C++ podporují strukturované zpracování výjimek (SEH), z důvodu větší přenositelnosti a flexibility doporučujeme použít zpracování výjimek jazyka C++ podle standardu ISO.Nicméně v existujícím kódu nebo pro určité druhy programů lze stále zpracování výjimek SEH používat.

Gramatika

try-except-statement :

__try compound-statement

__except ( expression ) compound-statement

Poznámky

Pomocí výjimek SEH lze zajistit, že jsou prostředky, jako například soubory a bloky paměti, správně uvolněny, pokud se aplikace neočekávaně ukončí.Lze také vyřešit určité problémy, například nedostatek paměti, pomocí stručného strukturovaného kódu, který není závislý na příkazech goto, nebo komplikované testování návratových kódů.

Příkazy try-except a try-finally uvedené v tomto článku jsou rozšíření jazyka C společností Microsoft.Podporují zpracování výjimek SEH tím, že aplikacím umožňují získat řízení programu po událostech, které by jinak ukončily provádění aplikace.Ačkoli zpracování výjimek SEH funguje se zdrojovými soubory jazyka C++, není konkrétně určeno pro jazyk C++.Pokud použijete zpracování výjimek SEH v programu jazyka C++ zkompilovaného pomocí možnosti /EH , včetně některých parametrů, destruktory místních objektů sice budou zavolány, ale další chování za běhu nemusí být podle vašeho očekávání. (Pro ilustraci si prohlédněte příklad dále v tomto článku.) Ve většině případů místo zpracování výjimek SEH doporučujeme použít zpracování výjimek jazyka C++ podle standardu ISO, které jazyk Visual C++ také podporuje.Pomocí zpracování výjimek jazyka C++ lze zajistit, že je váš kód přenositelnější a lze zpracovávat výjimky libovolného typu.

Pokud máte jakékoliv moduly jazyka C, které používají zpracování výjimek SEH, lze je míchat s moduly jazyka C++ , které používají zpracování výjimek jazyka C++.Informace naleznete v části Rozdíly ve zpracování výjimek.

Existují dva mechanismy zpracování výjimek SEH:

Tyto dva druhy obslužných rutin se liší, ale jsou podobné během procesu označovaném jako „uvolnění zásobníku“. Pokud dojde k výjimce, systém Windows hledá poslední nainstalovanou obslužnou rutinu, která je aktuálně aktivní.Obslužné rutiny mohou skončit jedním z následujících tří způsobů:

  • Selhat při rozpoznání výjimky a předat řízení dalším obslužným rutinám.

  • Rozpoznat výjimku, ale zamítnout ji.

  • Rozpoznat výjimku a zpracovat ji.

Obslužná rutina výjimky, která tuto výjimku rozpozná nemusí být ve funkci, která byla spuštěna, když k výjimce došlo.V některých případech může být ve funkci, která je v zásobníku mnohem výše.Aktuálně spuštěné funkce a všechny další funkce v zásobníku jsou ukončeny.Během tohoto procesu je zásobník uvolněn, tzn. že místní proměnné ukončených funkcí, pokud se nejedná o funkce deklarované jako static, jsou ze zásobníku odstraněny.

Při uvolnění zásobníku operační systém zavolá všechny obslužné rutiny ukončení, které jste pro každou funkci vytvořili.Pomocí obslužné rutiny ukončení lze uvolnit prostředky, které by jinak kvůli neobvyklému ukončení zůstaly otevřené.Pokud jste zadali kritický oddíl, lze obslužnou rutinu ukončení ukončit.Pokud se program ukončuje, lze provést další úklid, jako je například zavření a odebrání dočasných souborů.

Další informace naleznete v části:

Příklad

Jak bylo uvedeno dříve, destruktory místních objektů jsou zavolány, pokud v programu jazyka C++ použijete zpracování výjimek SEH a zkompilujete jej pomocí možnosti /EH s určitými parametry, například /EHsc nebo /EHa.Chování při spuštění však nemusí být podle vašeho očekávání, pokud používáte také výjimky jazyka C++.Následující příklad ukazuje tyto rozdíly v chování.

#include <stdio.h>
#include <Windows.h>
#include <exception>
 
class TestClass
{
public:
    ~TestClass()
    {
        printf("Destroying TestClass!\r\n");
    }
};
 
__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
    printf("Throwing C++ exception\r\n");
    throw std::exception("");
#else
    printf("Triggering SEH exception\r\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\r\n");
    }
 
    return 0;
}

Použijete-li možnost /EHsc ke kompilaci tohoto kódu a místní test řízení CPPEX není definován, pak se destruktor třídy TestClass nevykoná a výstup bude vypadat takto:

  

Použijete-li možnost /EHsc ke kompilaci kódu a místní test řízení CPPEX je definován pomocí možnosti /DCPPEX (tak, aby se vyvolala výjimka jazyka C++), pak se destruktor třídy TestClass provede a výstup bude vypadat takto:

  

Použijete-li možnost /EHa ke kompilaci kódu, pak se destruktor třídy TestClass provede bez ohledu na to, zda byla výjimka vyvolána pomocí příkazu std::throw nebo vyvolána pomocí zpracování výjimek SEH (CPPEX definované nebo ne).Výstup vypadá takto:

  

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

Viz také

Referenční dokumentace

Zpracování výjimek v jazyce Visual C++

Klíčová slova jazyka C++

<exception>

Koncepty

Ošetření chyb a výjimek (moderní verze jazyka C++)

Další zdroje

Strukturované zpracování výjimky (Windows)