Ošetření strukturovaných výjimek v C++
Hlavní rozdíl mezi zpracováním výjimek strukturovaného jazyka C (SEH) a zpracováním výjimek jazyka C++ spočívá v tom, že model zpracování výjimek jazyka C++ se zabývá typy, zatímco model strukturovaného zpracování výjimek jazyka C se zabývá výjimkami jednoho typu; konkrétně , unsigned int
. To znamená, že výjimky jazyka C jsou identifikovány celočíselnou hodnotou bez znaménka, zatímco výjimky jazyka C++ jsou identifikovány datovým typem. Když je v jazyce C vyvolána strukturovaná výjimka, každá možná obslužná rutina spustí filtr, který prozkoumá kontext výjimky jazyka C a určí, jestli má výjimku přijmout, předat ji jiné obslužné rutině nebo ji ignorovat. Jakmile je vyvolána výjimka v jazyce C++, může být libovolného typu.
Druhý rozdíl spočívá v tom, že model zpracování strukturovaných výjimek jazyka C se označuje jako asynchronní, protože výjimky se vyskytují sekundární pro normální tok řízení. Mechanismus zpracování výjimek jazyka C++ je plně synchronní, což znamená, že k výjimkám dochází pouze v případě, že jsou vyvolány.
Pokud použijete možnost kompilátoru /EHs nebo /EHsc , žádné obslužné rutiny výjimek jazyka C++ nezpracují strukturované výjimky. Tyto výjimky jsou zpracovávány pouze strukturovanými __except
obslužnými rutinami výjimek nebo __finally
obslužnými rutinami strukturovaného ukončení. Informace najdete v tématu Strukturované zpracování výjimek (C/C++).
Pokud je v programu jazyka C++ vyvolána výjimka jazyka C, je možné ji zpracovat pomocí strukturované obslužné rutiny výjimky s přidruženým filtrem nebo obslužnou rutinou jazyka C++catch
, podle toho, co je dynamicky blíž kontextu výjimky. Tento ukázkový program C++ například vyvolá výjimku jazyka C v kontextu jazyka C++ try
:
Příklad – Zachycení výjimky jazyka C v bloku zachycení jazyka C++
// exceptions_Exception_Handling_Differences.cpp
// compile with: /EHa
#include <iostream>
using namespace std;
void SEHFunc( void );
int main() {
try {
SEHFunc();
}
catch( ... ) {
cout << "Caught a C exception."<< endl;
}
}
void SEHFunc() {
__try {
int x, y = 0;
x = 5 / y;
}
__finally {
cout << "In finally." << endl;
}
}
In finally.
Caught a C exception.
Třídy obálky výjimek jazyka C
V jednoduchém příkladu jako výše lze výjimku jazyka C zachytit pouze obslužnou rutinou se třemi tečkou (...). catch
Obslužné rutině není dodána žádná informace o typu nebo povaze výjimky. I když tato metoda funguje, v některých případech můžete chtít definovat transformaci mezi dvěma modely zpracování výjimek, aby každá výjimka jazyka C byla přidružena ke konkrétní třídě. Chcete-li jej transformovat, můžete definovat třídu "obálka" výjimky jazyka C, která se dá použít nebo odvozena, aby bylo možné přiřadit určitý typ třídy výjimce jazyka C. Každá výjimka jazyka C tak může být zpracována zvlášť konkrétní obslužnou rutinou jazyka C++ catch
místo všech v jedné obslužné rutině.
Třída zabalení může obsahovat rozhraní skládající se z některých členských funkcí, které určují hodnotu výjimky a které přistupují k rozšířeným kontextovým informacím poskytnutým modelem zpracování výjimek jazyka C. Můžete také chtít definovat výchozí konstruktor a konstruktor, který přijímá unsigned int
argument (pro poskytnutí základní reprezentace výjimek jazyka C) a bitový konstruktor kopírování. Tady je možná implementace třídy obálky výjimek jazyka C:
// exceptions_Exception_Handling_Differences2.cpp
// compile with: /c
class SE_Exception {
private:
SE_Exception() {}
SE_Exception( SE_Exception& ) {}
unsigned int nSE;
public:
SE_Exception( unsigned int n ) : nSE( n ) {}
~SE_Exception() {}
unsigned int getSeNumber() {
return nSE;
}
};
Chcete-li použít tuto třídu, nainstalujte vlastní funkci překladu výjimek jazyka C, která je volána interním mechanismem zpracování výjimek při každém vyvolání výjimky jazyka C. V rámci funkce překladu můžete vyvolat libovolnou SE_Exception
typovou výjimku (třeba typ nebo typ třídy odvozený z SE_Exception
), který lze zachytit odpovídající obslužnou rutinou jazyka C++ catch
. Funkce překladu může místo toho vrátit, což znamená, že nezpracovala výjimku. Pokud samotná funkce překladu vyvolá výjimku jazyka C, zavolá se ukončení .
Pokud chcete zadat vlastní funkci překladu , zavolejte funkci _set_se_translator s názvem funkce překladu jako jeho jediným argumentem. Funkce překladu, kterou napíšete, se volá jednou pro každé vyvolání funkce v zásobníku, který obsahuje try
bloky. Neexistuje žádná výchozí funkce překladu; Pokud ho nezadáte voláním _set_se_translator, lze výjimku jazyka C zachytit pouze obslužnou rutinou tří teček catch
.
Příklad – Použití vlastní funkce překladu
Následující kód například nainstaluje vlastní funkci překladu a poté vyvolá výjimku jazyka C, která je zabalena do třídy SE_Exception
:
// exceptions_Exception_Handling_Differences3.cpp
// compile with: /EHa
#include <stdio.h>
#include <eh.h>
#include <windows.h>
class SE_Exception {
private:
SE_Exception() {}
unsigned int nSE;
public:
SE_Exception( SE_Exception& e) : nSE(e.nSE) {}
SE_Exception(unsigned int n) : nSE(n) {}
~SE_Exception() {}
unsigned int getSeNumber() { return nSE; }
};
void SEFunc() {
__try {
int x, y = 0;
x = 5 / y;
}
__finally {
printf_s( "In finally\n" );
}
}
void trans_func( unsigned int u, _EXCEPTION_POINTERS* pExp ) {
printf_s( "In trans_func.\n" );
throw SE_Exception( u );
}
int main() {
_set_se_translator( trans_func );
try {
SEFunc();
}
catch( SE_Exception e ) {
printf_s( "Caught a __try exception with SE_Exception.\n" );
printf_s( "nSE = 0x%x\n", e.getSeNumber() );
}
}
In trans_func.
In finally
Caught a __try exception with SE_Exception.
nSE = 0xc0000094
Viz také
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