Compartilhar via


/EH (Modelo de tratamento de exceção)

Especifica o suporte ao modelo de tratamento de exceção gerado pelo compilador. Os argumentos especificam se a sintaxe catch(...) deve ser aplicada a exceções estruturadas e padrão do C++, se é presumido que o código extern "C" throw exceções e se é necessário otimizar determinadas verificações noexcept.

Sintaxe

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

Argumentos

a
Habilita o desenrolamento de pilha padrão do C++. Captura exceções estruturadas (assíncronas) e padrão (síncronas) do C++ quando você usa a sintaxe catch(...). /EHa substitui os argumentos /EHs e /EHc.

s
Habilita o desenrolamento de pilha padrão do C++. Captura apenas exceções padrão do C++ quando você usa a sintaxe catch(...). A menos que /EHc também seja especificado, o compilador pressupõe que as funções declaradas como extern "C" podem throw uma exceção do C++.

c
Quando usado com /EHs, o compilador pressupõe que as funções declaradas como extern "C" nunca throw uma exceção do C++. Não tem efeito quando usado com /EHa (ou seja, /EHca é equivalente a /EHa). /EHc será ignorado se /EHs ou /EHa não for especificado.

r
Informa ao compilador para sempre gerar verificações de encerramento de runtime para todas as funções noexcept. Por padrão, as verificações de runtime podem noexcept ser otimizadas se o compilador determinar que a função chama apenas funções que não são de lançamento. Essa opção fornece conformidade estrita do C++ ao custo de algum código extra. /EHr será ignorado se /EHs ou /EHa não for especificado.

-
Limpa o argumento de opção anterior. Por exemplo, /EHsc- é interpretado como /EHs /EHc- e é equivalente a /EHs.

Argumentos /EH podem ser especificados separadamente ou combinados, em qualquer ordem. Se mais de uma instância do mesmo argumento for especificada, a última substituirá as anteriores. Por exemplo, /EHr- /EHc /EHs é o mesmo que /EHscr- e /EHscr- /EHr tem o mesmo efeito que /EHscr.

Comentários

Comportamento padrão de tratamento de exceção

O compilador sempre gera código que dá suporte ao tratamento assíncrono de exceção estruturada (SEH). Por padrão (ou seja, se nenhuma opção /EHsc, /EHs ou /EHa for especificada), o compilador dará suporte a manipuladores SEH na cláusula catch(...) nativa do C++. No entanto, ele também gera um código que dá apenas suporte parcial a exceções do C++. O código de desenrolamento de exceção padrão não destrói objetos do C++ automaticamente fora dos blocos try que saem do escopo devido a uma exceção. Vazamentos de recursos e comportamento indefinido podem ocorrer quando uma exceção C++ é lançada.

Tratamento padrão de exceção do C++

Suporte completo do compilador para o modelo de tratamento de exceção padrão do C++ que desenrola objetos de pilha com segurança requer /EHsc (recomendado), /EHs ou /EHa.

Se você usar /EHs ou /EHsc, as cláusulas catch(...) não catch exceções estruturadas assíncronas. As violações de acesso e exceções gerenciadas System.Exception não são capturadas. E, objetos no escopo durante a ocorrência de uma exceção assíncrona não são destruídos, mesmo que o código lide com a exceção assíncrona. Esse comportamento é um argumento para deixar exceções estruturadas sem tratamento. Em vez disso, considere essas exceções como fatais.

Quando você usa /EHs ou /EHsc, o compilador pressupõe que as exceções só podem acontecer em uma instrução throw ou em uma chamada de função. Essa suposição permite que o compilador elimine o código para acompanhar o tempo de vida de muitos objetos que não podem ser desenrolados, o que pode reduzir significativamente o tamanho do código. Se você usar /EHa, a imagem executável poderá ser maior e mais lenta, pois o compilador não otimiza blocos try tão agressivamente. Ele também para em filtros de exceção que limpam automaticamente objetos locais, mesmo que o compilador não veja nenhum código que possa throw uma exceção do C++.

Tratamento de exceções estruturadas e padrão do C++

A opção do compilador /EHa permite o desenrolamento de pilha seguro para exceções assíncronas e exceções do C++. Ela dá suporte ao tratamento de exceções padrão e estruturadas do C++ usando a cláusula nativa catch(...) do C++. Para implementar o SEH sem especificar /EHa, você pode usar as sintaxes __try, __except e __finally. Para obter mais informações, confira Tratamento de exceções estruturadas.

Importante

Especificar /EHa e tentar lidar com todas as exceções usando catch(...) pode ser perigoso. Na maioria dos casos, as exceções assíncronas são irrecuperáveis e devem ser consideradas fatais. Capturá-las e continuar pode causar o corrompimento do processo e gerar bugs que são difíceis de localizar e corrigir.

Ainda que o Windows e o Visual C++ ofereçam suporte para SEH, recomendamos o uso do tratamento de exceções do C++ padrão ISO (/EHsc ou /EHs). Isso torna seu código mais portátil e flexível. Talvez você ainda precise usar SEH em código herdado ou em determinados tipos de programas. Ele é necessário no código compilado para dar suporte ao common language runtime (/clr), por exemplo. Para obter mais informações, confira Tratamento de exceções estruturadas.

Recomendamos que você nunca vincule arquivos de objeto compilados usando /EHa com aqueles compilados usando /EHs ou /EHsc no mesmo módulo executável. Se você tiver que tratar uma exceção assíncrona usando /EHa em qualquer parte do módulo, use /EHa para compilar todo o código no módulo. Você pode usar a sintaxe de tratamento de exceções estruturadas no mesmo módulo do código que é compilado usando /EHs. No entanto, você não pode misturar a sintaxe SEH com try, throw e catch do C++ na mesma função.

Use /EHa se quiser catch uma exceção que seja gerada por algo diferente de throw. Este exemplo gera e captura uma exceção estruturada:

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

Tratamento de exceção em /clr

A opção /clr implica em /EHa (isto é, /clr /EHa é redundante). O compilador gera um erro se /EHs ou /EHsc for usado após /clr. As otimizações não afetam esse comportamento. Quando uma exceção é capturada, o compilador invoca os destruidores de classe para qualquer objeto que esteja no mesmo escopo da exceção. Se uma exceção não for capturada, esses destruidores não serão executados.

Para obter informações sobre as restrições do tratamento de exceções em /clr, confira _set_se_translator.

Verificações de exceção de runtime

A opção /EHr força verificações de encerramento de runtime em todas as funções que têm um atributo noexcept. Por padrão, as verificações de runtime podem ser otimizadas se o back-end do compilador determinar que uma função chama apenas funções que não são de lançamento . Funções que não geram são todas as funções que têm um atributo que especifica que nenhuma exceção pode ser lançada. Elas incluem funções marcadas com noexcept, throw(), __declspec(nothrow) e, quando /EHc for especificado, funções extern "C". As funções que não geram também incluem qualquer uma que o compilador tenha determinado que não é lançada por inspeção. Você pode definir explicitamente o comportamento padrão usando /EHr-.

Um atributo que não gera não é uma garantia de que as exceções não podem ser geradas por uma função. Ao contrário do comportamento de uma noexcept função, o compilador MSVC considera uma exceção lançada por uma função declarada usando throw(), __declspec(nothrow), ou extern "C" como comportamento indefinido. As funções que usam esses três atributos de declaração não impõem verificações de encerramento de runtime para exceções. Você pode usar a opção /EHr como auxílio para identificar esse comportamento indefinido, forçando o compilador a gerar verificações de runtime para exceções sem tratamento que escapam de uma função noexcept.

Definir a opção no Visual Studio ou programaticamente

Para definir esta opção do compilador no ambiente de desenvolvimento do Visual Studio

  1. Abra a caixa de diálogo Páginas de Propriedades do projeto. Para obter detalhes, confira Definir as propriedades de build e do compilador do C++ no Visual Studio.

  2. Selecione Propriedades de Configuração>C/C++>Geração de Código.

  3. Modifique a propriedade Habilitar Exceções do C++.

    Ou defina Habilitar Exceções do C++ como Não e, na página de propriedades da Linha de Comando, na caixa Opções Adicionais, adicione a opção do compilador.

Para definir essa opção do compilador via programação

Confira também

Opções do compilador do MSVC
Sintaxe da linha de comando do compilador do MSVC
Erros e tratamento de exceções
Especificações de exceção (throw)
Tratamento de exceções estruturado (C/C++)