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:
Obslužné rutiny výjimek nebo
__except
bloky, které mohou reagovat na výjimku nebo ji zavřít nafilter-expression
základě hodnoty. Další informace najdete vtry-except
příkazu.Obslužné rutiny ukončení nebo
__finally
bloky, které se vždy volají, ať už výjimka způsobuje ukončení nebo ne. Další informace najdete vtry-finally
příkazu.
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)
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro