Condividi tramite


try-except - istruzione

L'istruzione try-except è un'estensione specifica di Microsoft che supporta la gestione strutturata delle eccezioni nei linguaggi C e C++.

    // . . .
    __try {
        // guarded code
    }
    __except ( /* filter expression */ ) {
        // termination code
    }
    // . . .

Grammatica

try-except-statement:
__try compound-statement __except ( expression ) compound-statement

Osservazioni:

L'istruzione try-except è un'estensione Microsoft per i linguaggi C e C++. Consente alle applicazioni di destinazione di ottenere il controllo quando si verificano eventi che normalmente terminano l'esecuzione del programma. Tali eventi sono denominati eccezioni strutturate o eccezioni per brevità. Il meccanismo che gestisce queste eccezioni è denominato gestione delle eccezioni strutturata (SEH).

Per informazioni correlate, vedere l'istruzione try-finally.

Le eccezioni possono essere basate su hardware o basate su software. La gestione strutturata delle eccezioni è utile anche quando le applicazioni non possono eseguire completamente il ripristino da eccezioni hardware o software. SEH consente di visualizzare le informazioni sugli errori e di intercettare lo stato interno dell'applicazione per diagnosticare il problema. È particolarmente utile per problemi intermittenti che non sono facili da riprodurre.

Nota

La gestione eccezioni strutturata funziona con i file Win32 per i file di origine C++ e C. Tuttavia, non è progettato specificamente per C++. È possibile garantire maggiore portabilità del codice tramite la gestione delle eccezioni C++. Inoltre, la gestione eccezioni C++ è più flessibile, in quanto può gestire le eccezioni di qualsiasi tipo. Per i programmi C++, è consigliabile usare la gestione delle eccezioni C++ nativa: istruzioni try, catch e throw .

L'istruzione composta dopo la __try clausola è il corpo o la sezione sorvegliata . L'espressione __except è nota anche come espressione di filtro . Il valore determina la modalità di gestione dell'eccezione. L'istruzione composta dopo la clausola __except è il gestore dell'eccezione. Il gestore specifica le azioni da eseguire se viene generata un'eccezione durante l'esecuzione della sezione del corpo. L'esecuzione procede nel modo seguente:

  1. La sezione protetta viene eseguita.

  2. Se non si verifica alcuna eccezione durante l'esecuzione della sezione protetta, l'esecuzione continuerà nell'istruzione dopo la clausola __except.

  3. Se si verifica un'eccezione durante l'esecuzione della sezione sorvegliata o in qualsiasi routine chiamata alla sezione sorvegliata, l'espressione __except viene valutata. I tre valori possibili sono:

    • EXCEPTION_CONTINUE_EXECUTION (-1) Eccezione ignorata. Continuare l'esecuzione nel punto in cui si è verificata l'eccezione.

    • EXCEPTION_CONTINUE_SEARCH (0) Eccezione non riconosciuta. Continuare a cercare nello stack un gestore, prima di tutto per contenere try-except le istruzioni, quindi per i gestori con la precedenza più alta successiva.

    • EXCEPTION_EXECUTE_HANDLER (1) Viene riconosciuta l'eccezione. Trasferire il controllo al gestore eccezioni eseguendo l'istruzione composta, quindi continuare l'esecuzione __except dopo il __except blocco.

L'espressione __except viene valutata come espressione C. È limitato a un singolo valore, all'operatore di espressione condizionale o all'operatore virgola. Se è necessaria un'elaborazione più estesa, l'espressione può chiamare una routine che restituisce uno dei tre valori sopra elencati.

Ogni applicazione può essere associata al proprio gestore di eccezioni.

Non è valido passare a un'istruzione __try , ma valida per saltare da uno. Il gestore eccezioni non viene chiamato se un processo viene terminato al centro dell'esecuzione di un'istruzione try-except .

Per la compatibilità con le versioni precedenti, _try, _except e _leave sono sinonimi per __try, __excepte __leave a meno che non sia specificata l'opzione del compilatore /Za (Disabilita estensioni del linguaggio).

Parola chiave __leave

La __leave parola chiave è valida solo all'interno della sezione sorvegliata di un'istruzione try-except e il relativo effetto consiste nel passare alla fine della sezione sorvegliata. L'esecuzione continua con la prima istruzione dopo il gestore dell'eccezione.

Un'istruzione goto può anche uscire dalla sezione sorvegliata e non degrada le prestazioni come in un'istruzione try-finally . Questo perché la rimozione dello stack non si verifica. È tuttavia consigliabile usare la __leave parola chiave anziché un'istruzione goto . Il motivo è che è meno probabile che si commette un errore di programmazione se la sezione sorvegliata è grande o complessa.

Funzioni intrinseche di gestione delle eccezioni strutturate

La gestione strutturata delle eccezioni fornisce due funzioni intrinseche disponibili per l'uso con l'istruzione try-except GetExceptionCode e GetExceptionInformation.

GetExceptionCode restituisce il codice (intero a 32 bit) dell'eccezione.

La funzione GetExceptionInformation intrinseca restituisce un puntatore a una struttura EXCEPTION_POINTERS contenente informazioni aggiuntive sull'eccezione. Tramite questo puntatore, è possibile accedere allo stato del computer esistente al momento di un'eccezione hardware. La struttura è analoga alla seguente:

typedef struct _EXCEPTION_POINTERS {
    PEXCEPTION_RECORD ExceptionRecord;
    PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

I tipi di PEXCEPTION_RECORD puntatore e PCONTEXT sono definiti nel file <di inclusione winnt.h> e _CONTEXT _EXCEPTION_RECORD sono definiti nel file <di inclusione excpt.h>

È possibile usare GetExceptionCode all'interno del gestore eccezioni. Tuttavia, è possibile usare GetExceptionInformation solo all'interno dell'espressione di filtro delle eccezioni. Le informazioni a cui punta si trova in genere nello stack e non sono più disponibili quando il controllo viene trasferito al gestore eccezioni.

La funzione intrinseca AbnormalTermination è disponibile all'interno di un gestore di terminazione. Restituisce 0 se il corpo dell'istruzione try-finally termina in sequenza. In tutti gli altri casi, restituisce 1.

<excpt.h> definisce alcuni nomi alternativi per questi oggetti intrinseci:

GetExceptionCode equivale a _exception_code

GetExceptionInformation equivale a _exception_info

AbnormalTermination equivale a _abnormal_termination

Esempio

// 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");
}

Output

hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
        abnormal
in except
world

Vedi anche

Scrittura di un gestore eccezioni
Structured Exception Handling (C/C++)
Parole chiave