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

Strukturované zpracování výjimek (SEH) je rozšíření společnosti Microsoft pro jazyk C, které zpracovává určité výjimečné situace v kódu, například hardwarové chyby, řádným způsobem. i když Windows a Microsoft C++ podporují SEH, doporučujeme, abyste používali zpracování výjimek jazyka C++ standardu ISO. Díky tomu je váš kód lépe přenosný a flexibilní. Chcete-li však zachovat stávající kód nebo konkrétní druhy programů, bude pravděpodobně nutné použít SEH.

Specifické pro společnost Microsoft:

Gramatika

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

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

Poznámky

Pomocí SEH můžete zajistit, aby prostředky, jako jsou paměťové bloky a soubory, byly vydány správně, pokud se provádění nečekaně ukončí. Můžete také zpracovat konkrétní problémy, například nedostatečné množství paměti – pomocí stručného strukturovaného kódu, který nespoléhá na goto příkazy nebo vést testování návratových kódů.

try-exceptPříkazy a try-finally uvedené v tomto článku jsou rozšířeními společnosti Microsoft pro jazyk C. Podporují SEH tím, že umožňují aplikacím převzít řízení programu po událostech, které by jinak ukončily provádění. I když SEH funguje se zdrojovými soubory C++, není speciálně navržen pro C++. Použijete-li SEH v programu C++, který kompilujete pomocí možnosti nebo /EHsc , jsou volány destruktory místních objektů, ale jiné chování při provádění nemusí být to, co očekáváte. Ilustraci najdete v příkladu dále v tomto článku. Ve většině případů místo SEH doporučujeme používat standardní zpracování výjimek C++ Standard c++, které kompilátor Microsoft C++ podporuje také. Pomocí zpracování výjimek jazyka C++ můžete zajistit, aby byl váš kód lépe přenosný a můžete zpracovat výjimky libovolného typu.

Pokud máte kód jazyka C, který používá SEH, můžete jej kombinovat s kódem jazyka 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 souvisejí s procesem, který je známý jako odvinutí zásobníku. pokud dojde k strukturované výjimce, Windows vyhledá naposledy nainstalovanou obslužnou rutinu výjimky, která je aktuálně aktivní. Obslužná rutina může provést jednu ze tří věcí:

  • Nepodařilo se rozpoznat výjimku a předat řízení jiným obslužným rutinám.

  • Rozpoznat výjimku, ale zavřít ji.

  • Rozpoznat výjimku a zpracovat ji.

Obslužná rutina výjimky, která rozpozná výjimku, nesmí být ve funkci, která byla spuštěna v okamžiku, 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 rámce zásobníku jsou ukončeny. Během tohoto procesu se zásobník odblokuje . To znamená, že místní nestatické proměnné ukončených funkcí se od zásobníku vymažou.

Při uvolňování zásobníku volá operační systém jakékoli obslužné rutiny ukončení, které jste napsali pro jednotlivé funkce. Pomocí obslužné rutiny ukončení vyčistěte prostředky, které by jinak zůstaly otevřené z důvodu neobvyklého ukončení. Pokud jste zadali kritickou část, můžete ji ukončit v obslužné rutině ukončení. Když se program ukončí, můžete provádět další údržbu úlohy, jako je zavření a odebrání dočasných souborů.

Další kroky

Příklad

Jak bylo uvedeno dříve, destruktory pro lokální objekty jsou volány, pokud používáte SEH v programu C++ a zkompilujete pomocí /EHa Možnosti nebo /EHsc . Nicméně chování při provádění nemusí být očekávaným způsobem, 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!\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 /EHsc -li pro zkompilování tohoto kódu, ale místní makro testovacího ovládacího prvku CPPEX není definováno, TestClass destruktor se nespustí. Výstup vypadá takto:

Triggering SEH exception
Executing SEH __except block

Použijete /EHsc -li ke kompilaci kódu a CPPEX je definována pomocí /DCPPEX (takže je vyvolána výjimka jazyka C++), TestClass destruktor spustí a výstup vypadá takto:

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

Použijete /EHa -li ke kompilaci kódu, TestClass destruktor spustí, zda byla výjimka vyvolána pomocí std::throw nebo pomocí SEH k aktivaci výjimky. To znamená, zda CPPEX je definována nebo nikoli. Výstup vypadá takto:

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

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

KONEC specifické pro Microsoft

Viz také

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