Condividi tramite


/EH (Modello di gestione delle eccezioni)

Specifica il supporto del modello di gestione delle eccezioni generato dal compilatore. Gli argomenti specificano se applicare catch(...) la sintassi alle eccezioni C++ strutturate e standard, se si presuppone che extern il codice "C" venga considerato eccezioni throw e se ottimizzare determinati noexcept controlli.

Sintassi

/EHa[-]
/EHs[-]
/EHc[-]
/EHr[-]

Argomenti

a
Abilita la rimozione dello stack C++ standard. Rileva le eccezioni C++ (sincrone) strutturate (asincrone) e standard quando si usa catch(...) la sintassi. /EHa esegue l'override di entrambi /EHs gli argomenti e /EHc .

s
Abilita la rimozione dello stack C++ standard. Rileva solo le eccezioni C++ standard quando si usa catch(...) la sintassi. A meno /EHc che non venga specificato anche, il compilatore presuppone che le funzioni dichiarate come extern "C" possano throw essere un'eccezione C++.

c
Se usato con /EHs, il compilatore presuppone che le funzioni dichiarate come extern "C" non siano mai throw un'eccezione C++. Non ha alcun effetto quando viene usato con /EHa (ovvero, /EHca equivale a /EHa). /EHc viene ignorato se /EHs o /EHa non vengono specificati.

r
Indica al compilatore di generare sempre controlli di terminazione di runtime per tutte le funzioni noexcept . Per impostazione predefinita, è possibile ottimizzare i controlli di runtime per noexcept se il compilatore che determina la funzione chiama solo funzioni non generanti. Questa opzione offre una rigorosa conformità C++ a costi di codice aggiuntivo. /EHr viene ignorato se /EHs o /EHa non vengono specificati.

-
Cancella l'argomento dell'opzione precedente. Ad esempio, /EHsc- viene interpretato come /EHs /EHc-e equivale a /EHs.

/EH gli argomenti possono essere specificati separatamente o combinati, in qualsiasi ordine. Se viene specificata più di un'istanza dello stesso argomento, l'ultima esegue l'override di quelle precedenti. Ad esempio, /EHr- /EHc /EHs è uguale /EHscr-a e /EHscr- /EHr ha lo stesso effetto di /EHscr.

Osservazioni:

Comportamento di gestione delle eccezioni predefinito

Il compilatore genera sempre codice che supporta la gestione asincrona delle eccezioni strutturate (SEH). Per impostazione predefinita, ovvero se non è specificata alcuna /EHscopzione , /EHso /EHa , il compilatore supporta SEH i gestori nella clausola C++ catch(...) nativa. Tuttavia, genera anche codice che supporta solo parzialmente le eccezioni C++. Il codice di rimozione delle eccezioni predefinito non elimina definitivamente gli oggetti C++ automatici all'esterno di try blocchi che escono dall'ambito a causa di un'eccezione. Le perdite di risorse e il comportamento non definito possono comportare la generazione di un'eccezione C++.

Gestione delle eccezioni C++ standard

Supporto completo del compilatore per il modello di gestione delle eccezioni C++ Standard che rimuove in modo sicuro gli oggetti stack richiede /EHsc (scelta consigliata), /EHso /EHa.

Se si usa /EHs o /EHsc, le catch(...) clausole non catch sono eccezioni strutturate asincrone. Tutte le violazioni di accesso e le eccezioni gestite System.Exception non vengono rilevate. Gli oggetti nell'ambito quando si verifica un'eccezione asincrona non vengono eliminati definitivamente, anche se il codice gestisce l'eccezione asincrona. Questo comportamento è un argomento per lasciare non gestite le eccezioni strutturate. Prendere invece in considerazione queste eccezioni irreversibili.

Quando si usa /EHs o /EHsc, il compilatore presuppone che le eccezioni possano verificarsi solo in un'istruzione o in una throw chiamata di funzione. Questo presupposto consente al compilatore di eliminare il codice per tenere traccia della durata di molti oggetti rimovibili, riducendo in modo significativo le dimensioni del codice. Se si usa /EHa, l'immagine eseguibile può essere più grande e lenta, perché il compilatore non ottimizza try i blocchi in modo aggressivo. Lascia anche nei filtri eccezioni che puliscono automaticamente gli oggetti locali, anche se il compilatore non visualizza codice che può throw essere un'eccezione C++.

Gestione delle eccezioni C++ strutturata e standard

L'opzione /EHa del compilatore consente la rimozione sicura dello stack sia per le eccezioni asincrone che per le eccezioni C++. Supporta la gestione delle eccezioni C++ standard e strutturate usando la clausola C++ catch(...) nativa. Per implementare SEH senza specificare /EHa, è possibile usare la __trysintassi , __excepte __finally . Per altre informazioni, vedere Gestione delle eccezioni strutturate.

Importante

Specificare e tentare /EHa di gestire tutte le eccezioni tramite catch(...) può essere pericoloso. Nella maggior parte dei casi, le eccezioni asincrone sono irreversibili e devono essere gestite come tali. Il tentativo di intercettarle per procedere potrebbe causare il danneggiamento del processo ed errori difficili da trovare e risolvere.

Anche se Windows e Visual C++ supportano SEH, è consigliabile usare la gestione delle eccezioni C++ standard ISO (/EHsc o /EHs). Rende il codice più portatile e flessibile. In alcuni casi potrebbe essere necessario usare SEH nel codice legacy o per determinati tipi di programmi. È necessario nel codice compilato per supportare Common Language Runtime (/clr), ad esempio. Per altre informazioni, vedere Gestione delle eccezioni strutturate.

È consigliabile non collegare mai i file oggetto compilati usando /EHa quelli compilati usando /EHs o /EHsc nello stesso modulo eseguibile. Se è necessario gestire un'eccezione asincrona usando /EHa un punto qualsiasi del modulo, usare /EHa per compilare tutto il codice nel modulo. È possibile usare la sintassi di gestione delle eccezioni strutturata nello stesso modulo del codice compilato usando /EHs. Tuttavia, non è possibile combinare la SEH sintassi con C++ try, throwe catch nella stessa funzione.

Usare /EHa se si vuole creare catch un'eccezione generata da un elemento diverso da un oggetto throw. In questo esempio viene generata e intercettata un'eccezione strutturata:

// compiler_options_EHA.cpp
// compile with: /EHa
#include <iostream>
#include <excpt.h>
using namespace std;

void fail()
{
    // generates SE and attempts to catch it using catch(...)
    try
    {
        int i = 0, j = 1;
        j /= i;   // This will throw a SE (divide by zero).
        printf("%d", j);
    }
    catch(...)
    {
        // catch block will only be executed under /EHa
        cout << "Caught an exception in catch(...)." << endl;
    }
}

int main()
{
    __try
    {
        fail();
    }

    // __except will only catch an exception here
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        // if the exception was not caught by the catch(...) inside fail()
        cout << "An exception was caught in __except." << endl;
    }
}

Gestione delle eccezioni in /clr

L'opzione /clr implica /EHa (vale a dire, /clr /EHa è ridondante). Il compilatore genera un errore se /EHs o /EHsc viene usato dopo /clr. Le ottimizzazioni non influiscono su questo comportamento. Quando viene rilevata un'eccezione, il compilatore richiama i distruttori della classe per tutti gli oggetti che si trovano nello stesso ambito dell'eccezione. Se non viene rilevata un'eccezione, questi distruttori non vengono eseguiti.

Per informazioni sulle restrizioni di gestione delle eccezioni in /clr, vedere _set_se_translator.

Controlli delle eccezioni di runtime

L'opzione /EHr forza i controlli di terminazione del runtime in tutte le funzioni con un noexcept attributo . Per impostazione predefinita, i controlli di runtime possono essere ottimizzati se il back-end del compilatore determina che una funzione chiama solo funzioni non generate . Le funzioni non generanti sono quelle che hanno un attributo che specifica l'impossibilità di generare eccezioni. Includono funzioni contrassegnate come noexcept, throw()__declspec(nothrow), e, quando /EHc viene specificato, extern "C" le funzioni. Le funzioni non generanti includono anche qualsiasi attributo determinato come non generante dal compilatore dopo un'ispezione. È possibile impostare in modo esplicito il comportamento predefinito usando /EHr-.

Un attributo non generato non garantisce che le eccezioni non possano essere generate da una funzione. A differenza del comportamento di una noexcept funzione, il compilatore MSVC considera un'eccezione generata da una funzione dichiarata usando throw(), __declspec(nothrow)o extern "C" come comportamento non definito. Le funzioni che usano questi tre attributi di dichiarazione non applicano i controlli di terminazione del runtime per le eccezioni. È possibile usare l'opzione /EHr per identificare questo comportamento non definito forzando il compilatore a generare controlli di runtime per le eccezioni non gestite che eseguano l'escape di una noexcept funzione.

Impostare l'opzione in Visual Studio o a livello di codice

Per impostare l'opzione del compilatore nell'ambiente di sviluppo di Visual Studio

  1. Aprire la finestra di dialogo Pagine delle proprietà del progetto. Per informazioni dettagliate, vedere Impostare il compilatore e le proprietà di compilazione.

  2. Selezionare Proprietà>di configurazione C/C++>Generazione codice.

  3. Modificare la proprietà Abilita eccezioni C++ .

    In alternativa, impostare Abilita eccezioni C++ su No, quindi nella casella Opzioni aggiuntive della pagina delle proprietà Riga di comando aggiungere l'opzione del compilatore.

Per impostare l'opzione del compilatore a livello di codice

Vedi anche

Opzioni del compilatore MSVC
Sintassi della riga di comando del compilatore MSVC
Errori e gestione delle eccezioni
Specifiche delle eccezioni (throw)
Structured Exception Handling (C/C++)