Obsługa wyjątków strukturalnych w języku C++
Główną różnicą między obsługą wyjątków ustrukturyzowanych języka C (SEH) i obsługą wyjątków C++ jest to, że transakcje modelu obsługi wyjątków w języku C++ w typach, podczas gdy model obsługi wyjątków ustrukturyzowanych języka C obsługuje wyjątki jednego typu; w szczególności . unsigned int
Oznacza to, że wyjątki języka C są identyfikowane przez niepodpisaną wartość całkowitą, podczas gdy wyjątki języka C++ są identyfikowane przez typ danych. Po wystąpieniu wyjątku strukturalnego w języku C każdy możliwy program obsługi wykonuje filtr, który sprawdza kontekst wyjątku języka C i określa, czy zaakceptować wyjątek, przekazać go do innej procedury obsługi, czy zignorować. Gdy wyjątek jest zgłaszany w języku C++, może być dowolnego typu.
Druga różnica polega na tym, że model obsługi wyjątków ustrukturyzowanych języka C jest określany jako asynchroniczny, ponieważ wyjątki występują pomocnicze do normalnego przepływu sterowania. Mechanizm obsługi wyjątków języka C++ jest w pełni synchroniczny, co oznacza, że wyjątki występują tylko wtedy, gdy są zgłaszane.
Jeśli używasz opcji /EHs lub /EHsc kompilatora, żadne procedury obsługi wyjątków języka C++ nie obsługują wyjątków strukturalnych. Te wyjątki są obsługiwane tylko przez __except
programy obsługi wyjątków ustrukturyzowanych lub __finally
procedury obsługi zakończenia ze strukturą. Aby uzyskać informacje, zobacz Obsługa wyjątków strukturalnych (C/C++).
W ramach /EHa opcji kompilatora, jeśli wyjątek języka C jest zgłaszany w programie C++, można go obsłużyć przez program obsługi wyjątków ze strukturą ze skojarzonym filtrem lub przez program obsługi języka C++catch
, w zależności od tego, która wartość jest dynamicznie zbliżona do kontekstu wyjątku. Na przykład ten przykładowy program C++ zgłasza wyjątek C wewnątrz kontekstu C++ try
:
Przykład — przechwytywanie wyjątku języka C w bloku catch języka 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.
Klasy otoki wyjątków języka C
W prostym przykładzie, tak jak powyżej, wyjątek języka C można przechwycić tylko przez program obsługi wielokropka (...). catch
Brak informacji na temat typu lub rodzaju wyjątku jest przekazywany do modułu obsługi. Chociaż ta metoda działa, w niektórych przypadkach można zdefiniować transformację między dwoma modelami obsługi wyjątków, tak aby każdy wyjątek C był skojarzony z określoną klasą. Aby przekształcić klasę, można zdefiniować klasę "otoki" wyjątku języka C, która może być używana lub pochodzi z klasy w celu przypisania określonego typu klasy do wyjątku C. W ten sposób każdy wyjątek języka C może być obsługiwany oddzielnie przez określoną procedurę obsługi języka C++ catch
, a nie wszystkie w jednej procedurze obsługi.
Klasa otoki może mieć interfejs składający się z niektórych funkcji składowych, które określają wartość wyjątku i dostęp do rozszerzonych informacji kontekstu wyjątku dostarczonych przez model wyjątków C. Możesz również zdefiniować domyślny konstruktor i konstruktor, który akceptuje unsigned int
argument (aby zapewnić podstawową reprezentację wyjątku języka C) i konstruktor kopiujący bitowo. Oto możliwa implementacja klasy otoki wyjątków języka 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;
}
};
Aby użyć tej klasy, zainstaluj niestandardową funkcję tłumaczenia wyjątków języka C wywoływaną przez mechanizm obsługi wyjątków wewnętrznych za każdym razem, gdy zgłaszany jest wyjątek języka C. W funkcji tłumaczenia można zgłosić dowolny typ wyjątku (np SE_Exception
. typ lub typ klasy pochodzącej z SE_Exception
klasy ), który może zostać przechwycony przez odpowiednią zgodną procedurę obsługi języka C++ catch
. Funkcja tłumaczenia może zamiast tego zwrócić wartość, która wskazuje, że nie obsługuje wyjątku. Jeśli sama funkcja tłumaczenia zgłasza wyjątek języka C, wywołana jest przerwanie .
Aby określić niestandardową funkcję tłumaczenia, wywołaj funkcję _set_se_translator nazwą funkcji tłumaczenia jako pojedynczy argument. Funkcja tłumaczenia, którą piszesz, jest wywoływana raz dla każdej wywołania funkcji na stosie, który zawiera try
bloki. Nie ma domyślnej funkcji tłumaczenia; Jeśli nie określisz go przez wywołanie _set_se_translator, wyjątek języka C może zostać przechwycony tylko przez program obsługi wielokropka catch
.
Przykład — używanie niestandardowej funkcji tłumaczenia
Na przykład, poniższy kod instaluje niestandardową funkcję tłumaczenia i następnie zgłasza wyjątek C, który jest otoczony przez klasę 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
Zobacz też
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla