Uso di un gestore eccezioni
Negli esempi seguenti viene illustrato l'uso di un gestore eccezioni.
Esempio 1
Il frammento di codice seguente usa la gestione strutturata delle eccezioni per verificare se un'operazione di divisione su due interi a 32 bit genererà un errore di divisione per zero. In questo caso, la funzione restituisce FAL edizione Standard; in caso contrario, restituisce TRUE.
BOOL SafeDiv(INT32 dividend, INT32 divisor, INT32 *pResult)
{
__try
{
*pResult = dividend / divisor;
}
__except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
return FALSE;
}
return TRUE;
}
Esempio 2
La funzione di esempio seguente chiama la funzione DebugBreak e usa la gestione strutturata delle eccezioni per verificare la presenza di un'eccezione del punto di interruzione. In caso affermativo, la funzione restituisce FAL edizione Standard; in caso contrario, restituisce TRUE.
L'espressione di filtro nell'esempio usa la funzione GetExceptionCode per controllare il tipo di eccezione prima di eseguire il gestore. Ciò consente al sistema di continuare la ricerca di un gestore appropriato se si verifica un altro tipo di eccezione.
Inoltre, l'uso dell'istruzione return nel blocco __try di un gestore eccezioni differisce dall'uso di return nel blocco __try di un gestore di terminazione, che causa una terminazione anomala del blocco __try. Si tratta di un uso valido dell'istruzione return in un gestore eccezioni.
BOOL CheckForDebugger()
{
__try
{
DebugBreak();
}
__except(GetExceptionCode() == EXCEPTION_BREAKPOINT ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
// No debugger is attached, so return FALSE
// and continue.
return FALSE;
}
return TRUE;
}
Restituisce solo EXCEPTION_EXECUTE_HANDLER da un filtro eccezioni quando è previsto il tipo di eccezione e l'indirizzo di errore è noto. È consigliabile consentire al gestore eccezioni predefinito di elaborare tipi di eccezione imprevisti e indirizzi di errore.
Esempio 3
Nell'esempio seguente viene illustrata l'interazione dei gestori annidati. La funzione RaiseException causa un'eccezione nel corpo sorvegliato di un gestore di terminazione che si trova all'interno del corpo sorvegliato di un gestore eccezioni. L'eccezione fa sì che il sistema valuti la funzione FilterFunction, il cui valore restituito a sua volta fa sì che venga richiamato il gestore eccezioni. Tuttavia, prima dell'esecuzione del blocco del gestore eccezioni, viene eseguito il blocco __finally del gestore di terminazione perché il flusso del controllo ha lasciato il blocco __try del gestore di terminazione.
DWORD FilterFunction()
{
printf("1 "); // printed first
return EXCEPTION_EXECUTE_HANDLER;
}
VOID main(VOID)
{
__try
{
__try
{
RaiseException(
1, // exception code
0, // continuable exception
0, NULL); // no arguments
}
__finally
{
printf("2 "); // this is printed second
}
}
__except ( FilterFunction() )
{
printf("3\n"); // this is printed last
}
}