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:
Chráněná část je spuštěna.
Nedojde-li za běhu chráněné části k žádné výjimce, pokračuje běh programu příkazem za klauzulí
__except
.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
, __except
a __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
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