Compartilhar via


Instrução try-except

A instrução try-except é uma extensão específica da Microsoft que dá suporte ao tratamento de exceções estruturadas nas linguagens C e C++.

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

Gramática

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

Comentários

A instrução try-except é uma extensão da Microsoft para as linguagens C e C++. Ela permite que os aplicativos de destino obtenham controle quando ocorrem eventos que normalmente encerram a execução do programa. Esses eventos são chamados de exceções estruturadas ou exceções para abreviar. O mecanismo que lida com essas exceções é chamado de SEH (tratamento de exceção estruturada).

Para obter informações relacionadas, confira a instrução try-finally.

As exceções podem ser baseadas em hardware ou software. O tratamento de exceções estruturadas é útil mesmo quando os aplicativos não podem se recuperar completamente de exceções de hardware ou software. O SEH possibilita exibir informações de erro e reter o estado interno do aplicativo para ajudar a diagnosticar o problema. É especialmente útil para problemas intermitentes que não são fáceis de reproduzir.

Observação

A manipulação de exceção estruturada funciona com Win32 para arquivos de código-fonte em C e C++. No entanto, não é projetada especificamente para C++. Você pode garantir que o código seja mais portátil usando a manipulação de exceção de C++. Além disso, a manipulação de exceção de C++ é mais flexível, pois pode tratar exceções de qualquer tipo. Para programas C++, recomendamos que você use instruções C++ nativas de tratamento de exceções: instruções try, catch e throw.

A instrução composta após a cláusula __try é a seção do corpo ou protegida. A expressão __except também é conhecida como a expressão de filtro. Seu valor determina como a exceção será tratada. A instrução composta após a cláusula __except é o manipulador de exceções. O manipulador especifica as ações a serem executadas se uma exceção for gerada durante a execução da seção do corpo. A execução procede da seguinte maneira:

  1. A seção protegida é executada.

  2. Se nenhuma exceção ocorrer durante a execução da seção protegida, a execução continuará na instrução após a cláusula __except.

  3. Se uma exceção ocorrer durante a execução de uma seção protegida ou em qualquer rotina chamada pela seção protegida, a expressão __except será avaliada. Há três valores possíveis:

    • EXCEPTION_CONTINUE_EXECUTION (-1) A exceção é descartada. Continue a execução no ponto onde ocorreu a exceção.

    • EXCEPTION_CONTINUE_SEARCH (0) A exceção não é reconhecida. Continue pesquisando manipuladores na pilha; primeiro os que contêm as instruções try-except, depois os que têm a próxima precedência mais alta.

    • EXCEPTION_EXECUTE_HANDLER (1) A exceção é reconhecida. Transfere o controle para o manipulador de exceção executando a instrução composta __except e continua a execução após o bloco __except.

A expressão __except é avaliada como uma expressão C. Ela é limitada a um único valor, o operador de expressão condicional ou o operador de vírgula. Se um processamento mais extenso for necessário, a expressão poderá chamar uma rotina que retorne um dos três valores listados acima.

Cada aplicativo pode ter seu próprio manipulador de exceção.

Isso não é válido para ir para uma instrução __try, mas é válido para sair de uma. O manipulador de exceção não é chamado se um processo é encerrado no meio da execução de uma instrução try-except.

Para compatibilidade com versões anteriores, _try, _except e _leave são sinônimos para __try, __excepte __leave a menos que a opção /Za do compilador (desabilitar extensões de idioma) esteja especificada.

A palavra-chave __leave

A palavra-chave __leave é válida somente na seção protegida de uma instrução try-except, e seu efeito é ir diretamente para o final da seção protegida. A execução continua na primeira instrução após o manipulador de exceção.

Uma instrução goto também pode sair da seção protegida, e isso não afeta o desempenho como em uma instrução try-finally. Isso é devido porque não ocorre o desenrolamento de pilha. No entanto, recomendamos que você use a palavra-chave __leave em vez de uma instrução goto. O motivo é que você tem menos probabilidade de cometer um erro de programação se a seção protegida for grande ou complexa.

Funções intrínsecas da manipulação de exceções estruturadas

A manipulação de exceção estruturada fornece duas funções intrínsecas que estão disponíveis para uso na instrução try-except: GetExceptionCode e GetExceptionInformation.

GetExceptionCode retorna o código (um inteiro de 32 bits) da exceção.

A função intrínseca GetExceptionInformation retorna um ponteiro para uma estrutura EXCEPTION_POINTERS que contém informações adicionais sobre a exceção. Por esse ponteiro, você pode acessar qual era o estado do computador no momento em que ocorreu uma exceção de hardware. A estrutura é a seguinte:

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

Os tipos de ponteiro PEXCEPTION_RECORD e PCONTEXT são definidos no arquivo de inclusão <winnt.h> e _EXCEPTION_RECORD e _CONTEXT são definidos no arquivo de inclusão <excpt.h>

Você pode usar GetExceptionCode dentro do manipulador de exceção. Porém, você pode usar GetExceptionInformation somente na expressão de filtro de exceção. As informações para as quais ele aponta ficam normalmente na pilha e não estarão mais disponíveis quando o controle for transferido para o manipulador de exceção.

A função intrínseca AbnormalTermination está disponível dentro de um manipulador de término. Ela retornará 0 se o corpo da instrução try-finally terminar em sequência. Em todos os outros casos, retorna 1.

<excpt.h> define nomes alternativos para estes intrínsecos:

GetExceptionCode equivale a _exception_code

GetExceptionInformation equivale a _exception_info

AbnormalTermination equivale a _abnormal_termination

Exemplo

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

Saída

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

Confira também

Escrevendo um manipulador de exceção
Tratamento de exceções estruturado (C/C++)
Palavras-chave