Structured Exception Handling (C/C++)

La gestione strutturata delle eccezioni (edizione Standard H) è un'estensione Microsoft per C e C++ per gestire determinate situazioni di codice eccezionali, ad esempio errori hardware, normalmente. Anche se Windows e Microsoft C++ supportano edizione Standard H, è consigliabile usare la gestione delle eccezioni C++ standard ISO nel codice C++. Rende il codice più portatile e flessibile. Tuttavia, per mantenere il codice esistente o per determinati tipi di programmi, potrebbe comunque essere necessario usare edizione Standard H.

Specifico di Microsoft:

Grammatica

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

try-finally-statement :
__try compound-statement __finally compound-statement

Osservazioni:

Con edizione Standard H, è possibile assicurarsi che le risorse, ad esempio blocchi di memoria e file, vengano rilasciati correttamente se l'esecuzione termina in modo imprevisto. È anche possibile gestire problemi specifici, ad esempio memoria insufficiente, usando codice strutturato conciso che non si basa su goto istruzioni o test elaborati dei codici restituiti.

Le try-except istruzioni e try-finally indicate in questo articolo sono estensioni Microsoft per i linguaggi C e C++. Supportano la gestione delle eccezioni strutturata permettendo alle applicazioni di ottenere il controllo di un programma dopo eventi che altrimenti terminerebbero l'esecuzione. Anche se la gestione delle eccezioni strutturata può essere usata con file di origine C++, non è stata progettata in modo specifico per C++. Se si usa edizione Standard H in un programma C++ compilato usando l'opzione /EHa o /EHsc , vengono chiamati distruttori per gli oggetti locali, ma altri comportamenti di esecuzione potrebbero non essere quello previsto. Per un'illustrazione, vedere l'esempio più avanti in questo articolo. Nella maggior parte dei casi, anziché edizione Standard H è consigliabile usare la gestione delle eccezioni C++ standard ISO. L'uso della gestione delle eccezioni C++ permette di assicurare una maggiore portabilità del codice e la gestione di qualsiasi tipo di eccezione.

Se si dispone di codice C che usa edizione Standard H, è possibile combinarlo con il codice C++ che usa la gestione delle eccezioni C++. Per informazioni, vedere Gestire eccezioni strutturate in C++.

Sono disponibili due meccanismi per la gestione delle eccezioni strutturata:

  • Gestori eccezioni, o __except blocchi, che possono rispondere o ignorare l'eccezione in base al filter-expression valore . Per altre informazioni, vedere try-except l'istruzione .

  • Gestori di terminazione, o __finally blocchi, che vengono sempre chiamati, indipendentemente dal fatto che un'eccezione causi o meno la terminazione. Per altre informazioni, vedere try-finally l'istruzione .

Questi due tipi di gestori sono distinti, ma sono strettamente correlati tramite un processo noto come rimozione dello stack. Quando si verifica un'eccezione strutturata, Windows cerca il gestore eccezioni installato più di recente attualmente attivo. Il gestore può procedere nei tre modi seguenti:

  • Non è possibile riconoscere l'eccezione e passare il controllo ad altri gestori (EXCEPTION_CONTINUE_SEARCH).

  • Riconoscere l'eccezione ma ignorarla (EXCEPTION_CONTINUE_EXECUTION).

  • Riconoscere l'eccezione e gestirla (EXCEPTION_EXECUTE_HANDLER).

È possibile che il gestore di eccezioni che riconosce l'eccezione non si trovi nella funzione che era in esecuzione quando si è verificata l'eccezione. Può trovarsi in una funzione molto più alta nello stack. La funzione attualmente in esecuzione e tutte le altre funzioni nel frame dello stack vengono terminate. Durante questo processo, lo stack viene scollegato. Ovvero, le variabili locali non statiche delle funzioni terminate vengono cancellate dallo stack.

Durante la rimozione dello stack, il sistema operativo chiama eventuali gestori di terminazione scritti per ogni funzione. Usando un gestore di terminazione, si puliscono le risorse che altrimenti rimarranno aperte a causa di una terminazione anomala. Se è stata immessa una sezione critica, è possibile chiuderla nel gestore di terminazione. Quando il programma verrà arrestato, è possibile eseguire altre attività di manutenzione, ad esempio la chiusura e la rimozione di file temporanei.

Passaggi successivi

Esempio

Come indicato in precedenza, i distruttori per gli oggetti locali vengono chiamati se si usa edizione Standard H in un programma C++ e compilarlo usando l'opzione /EHa o /EHsc . Tuttavia, il comportamento durante l'esecuzione potrebbe non essere quello previsto se si usano anche eccezioni C++. Questo esempio illustra queste differenze comportamentali.

#include <stdio.h>
#include <Windows.h>
#include <exception>

class TestClass
{
public:
    ~TestClass()
    {
        printf("Destroying TestClass!\n");
    }
};

__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
    printf("Throwing C++ exception\n");
    throw std::exception("");
#else
    printf("Triggering SEH exception\n");
    volatile int *pInt = 0x00000000;
    *pInt = 20;
#endif
}

__declspec(noinline) void TestExceptions()
{
    TestClass d;
    TestCPPEX();
}

int main()
{
    __try
    {
        TestExceptions();
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        printf("Executing SEH __except block\n");
    }

    return 0;
}

Se si usa /EHsc per compilare questo codice ma la macro CPPEX del controllo di test locale non è definita, il TestClass distruttore non viene eseguito. L'output sarà simile al seguente:

Triggering SEH exception
Executing SEH __except block

Se si usa /EHsc per compilare il codice e CPPEX viene definito usando /DCPPEX (in modo che venga generata un'eccezione C++), il TestClass distruttore viene eseguito e l'output è simile al seguente:

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

Se si usa /EHa per compilare il codice, il TestClass distruttore esegue se è stata generata un'eccezione usando un'espressione C++ throw standard o usando edizione Standard H. Ovvero, se CPPEX è definito o meno. L'output sarà simile al seguente:

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

Per altre informazioni, vedere /EH (Modello di gestione delle eccezioni).

END Specifico di Microsoft

Vedi anche

Gestione delle eccezioni
Parole chiave
<exception>
Errori e gestione delle eccezioni
Gestione strutturata delle eccezioni (Windows)