try-except – příkaz
Specifické pro Microsoft
Následující syntaxe popisuje příkaz try-except:
__try
{
// guarded code
}
__except ( expression )
{
// exception handler code
}
Poznámky
Příkaz try-except je rozšířením jazyků C a C++ společností Microsoft, které umožňuje cílovým aplikacím získat kontrolu v případě, že dojde k událostem, které za normálních okolností ukončí běh programu.Tyto události jsou nazývány výjimkami a mechanismus, který se výjimkami zabývá, se nazývá strukturované zpracování výjimek.
Související informace naleznete v tématu Příkaz try-finally.
Výjimky mohou být hardwarové nebo softwarové.I v případech, kdy aplikace nemohou být zotaveny z hardwarových nebo softwarových výjimek, umožňuje strukturované zpracování výjimek zobrazit informace o chybě a zachytit vnitřní stav aplikace pro diagnostiku problému.To je užitečné zejména pro občasné problémy, které nelze snadno reprodukovat.
[!POZNÁMKA]
Strukturované zpracování výjimek funguje na architektuře Win32 pro zdrojové soubory jazyka C i C++.Pro jazyk C++ však není výslovně navržen.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++ je doporučeno použití mechanismu zpracování výjimek jazyka C++ (příkazy try, catch a throw).
Složený příkaz za klauzulí __try je tělem chráněné části.Složený příkaz po klauzuli __except je obslužnou rutinou výjimky.Obslužná rutina udává sadu akcí provedených v případě, že během provádění těla chráněné části dojde k vyvolání výjimky.Spuštění probíhá 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 k výjimce za běhu chráněné části nebo v jakékoliv rutině, kterou chráněná část zavolala, dojde, je vyhodnocen výraz__except (nazývaný výraz filtru) a jeho hodnota určuje, jak je výjimka zpracována.Existují tři hodnoty:
EXCEPTION_CONTINUE_EXECUTION (–1) Výjimka je ignorována.Program bude pokračovat tam, kde k výjimce došlo.
EXCEPTION_CONTINUE_SEARCH (0) Výjimka není rozpoznána.Program bude pokračovat v hledání obslužné rutiny v zásobníku, tedy nejprve odpovídající příkazy try-except, poté obslužné rutiny s druhou nejvyšší prioritou.
EXCEPTION_EXECUTE_HANDLER (1) Výjimka je rozpoznána.Řízení je převedeno na obslužnou rutinu událostí spuštěním složeného příkazu __except, poté běh programu pokračuje příkazy za blokem __except.
Jelikož je výraz __except vyhodnocován jako výraz jazyka C, je omezen na jedinou 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í povoleno přejít do příkazu __try, je však povoleno přejít mimo něj.Obslužná rutina výjimky není zavolána, je-li proces v průběhu provádění příkazu try-except ukončen.
Další informace naleznete ve článku znalostní báze Q315937 : POSTUPY: Zachycení přetečení zásobníku v aplikaci Visual C++.
Klíčové slovo __leave
Klíčové slovo __leave je platné pouze uvnitř chráněné části příkazu try-except a jeho účinkem je přechod na konec chráněné části.Běh programu pokračuje prvním příkazem za obslužnou rutinou výjimky.
Příkazem goto lze také přejít mimo chráněnou část a nesnižuje výkon jako v příkazu try-finally, protože nedochází k rozvíjení zásobníku.Je však doporučeno používat spíše klíčové slovo __leave namísto příkazu goto, protože tím lze snížit riziko programové chyby, je-li chráněný 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é lze použít spolu s příkazem try-except: GetExceptionCode a GetExceptionInformation.
Funkce GetExceptionCode vrací kód (32bitové celé číslo) výjimky.
Vnitřní funkce GetExceptionInformation vrací ukazatel na strukturu 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í.
struct _EXCEPTION_POINTERS {
EXCEPTION_RECORD *ExceptionRecord,
CONTEXT *ContextRecord }
Typy ukazatelů _EXCEPTION_RECORD a _CONTEXT jsou definovány v souboru hlaviček EXCPT.H.
Funkci GetExceptionCode lze použít uvnitř obslužné rutiny výjimky.Funkci GetExceptionInformation však lze použít pouze uvnitř výrazu filtru výjimky.Informace, na které ukazuje, jsou obecně umístěny na zásobníku a ve chvíli, kdy je řízení převedeno na obslužnou rutinu výjimky, již nedostupné.
Vnitřní funkce AbnormalTermination je k dispozici uvnitř obslužné rutiny ukončení.Funkce vrátí hodnotu 0, je-li tělo příkazu try-finally ukončeno sekvenčně.Ve všech ostatních případech vrátí hodnotu 1.
Soubor EXCPT.H pro tyto vnitřní funkce definuje několik alternativních názvů:
GetExceptionCode je ekvivalentem klauzule _exception_code
GetExceptionInformation je ekvivalentem klauzule _exception_info
AbnormalTermination je ekvivalentem klauzule _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ýsledek
hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
abnormal
in except
world
Specificka produktu Microsoft END