Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La differenza principale tra la gestione delle eccezioni strutturata C (SEH) e la gestione delle eccezioni C++ è che il modello di gestione delle eccezioni C++ gestisce i tipi, mentre il modello di gestione delle eccezioni strutturate C gestisce le eccezioni di un tipo; in particolare, unsigned int
. Ovvero, le eccezioni C sono identificate da un valore intero senza segno, mentre le eccezioni C++ sono identificate dal tipo di dati. Quando viene generata un'eccezione strutturata in C, ogni gestore possibile esegue un filtro che esamina il contesto dell'eccezione C e determina se accettare l'eccezione, passarla a un altro gestore o ignorarla. Quando viene generata un'eccezione in C++, può essere di qualsiasi tipo.
Una seconda differenza è che il modello di gestione delle eccezioni strutturate C viene definito asincrono, perché le eccezioni si verificano secondarie al normale flusso di controllo. Il meccanismo di gestione delle eccezioni C++ è completamente sincrono, il che significa che le eccezioni si verificano solo quando vengono generate.
Quando si usa l'opzione del compilatore /EHs o /EHsc , nessun gestore di eccezioni C++ gestisce eccezioni strutturate. Queste eccezioni vengono gestite solo da __except
gestori di eccezioni strutturati o __finally
gestori di terminazione strutturati. Per informazioni, vedere Structured Exception Handling (C/C++).
Nell'opzione del compilatore /EHa , se viene generata un'eccezione C in un programma C++, può essere gestita da un gestore di eccezioni strutturato con il filtro associato o da un gestore C++ catch
, a qualsiasi livello dinamico più vicino al contesto dell'eccezione. Ad esempio, questo programma C++ di esempio genera un'eccezione C all'interno di un contesto C++ try
:
Esempio: intercettare un'eccezione C in un blocco catch 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.
Classi wrapper di eccezione C
In un semplice esempio come quello precedente, l'eccezione C può essere intercettata solo da un gestore con puntini di sospensione (...). catch
Nessuna informazione sul tipo o la natura dell'eccezione viene comunicata al gestore. Anche se questo metodo funziona, in alcuni casi può essere necessario definire una trasformazione tra i due modelli di gestione delle eccezioni in modo che ogni eccezione C sia associata a una classe specifica. Per trasformarlo, è possibile definire una classe "wrapper" dell'eccezione C, che può essere usata o derivata da per attribuire un tipo di classe specifico a un'eccezione C. In questo modo, ogni eccezione C può essere gestita separatamente da un gestore C++ catch
specifico, anziché tutti in un singolo gestore.
La classe wrapper potrebbe avere un'interfaccia composta da alcune funzioni membro che determinano il valore dell'eccezione e che accedono alle informazioni sul contesto delle eccezioni estese fornite dal modello di eccezione C. È anche possibile definire un costruttore predefinito e un costruttore che accetta un unsigned int
argomento (per fornire la rappresentazione dell'eccezione C sottostante) e un costruttore di copia bit per bit. Ecco una possibile implementazione di una classe wrapper di eccezione 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;
}
};
Per usare questa classe, installare una funzione di conversione delle eccezioni C personalizzata chiamata dal meccanismo di gestione delle eccezioni interno ogni volta che viene generata un'eccezione C. All'interno della funzione di conversione è possibile generare qualsiasi eccezione tipizzata (ad esempio un SE_Exception
tipo o un tipo di classe derivato da SE_Exception
) che può essere intercettata da un gestore C++ catch
corrispondente appropriato. La funzione di conversione può invece restituire , che indica che non ha gestito l'eccezione. Se la funzione di conversione stessa genera un'eccezione C, viene chiamato terminate .
Per specificare una funzione di conversione personalizzata, chiamare la funzione di _set_se_translator con il nome della funzione di conversione come singolo argomento. La funzione di traduzione scritta viene chiamata una volta per ogni chiamata di funzione nello stack con try
blocchi. Non esiste alcuna funzione di traduzione predefinita; se non si specifica uno chiamando _set_se_translator, l'eccezione C può essere intercettata solo da un gestore con i puntini di sospensione catch
.
Esempio- Usare una funzione di traduzione personalizzata
Ad esempio, il codice riportato di seguito installa una funzione di conversione personalizzata, quindi genera un'eccezione C di cui viene eseguito il wrapping nella classe 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