Compartilhar via


Instrução try-except

A try-except instrução é uma extensão específica da Microsoft que dá suporte ao tratamento estruturado de exceções 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

Observações

A try-except instrução é uma extensão da Microsoft para as linguagens C e C++. Ele permite que 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 estruturado de exceções ).

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

As exceções podem ser baseadas em hardware ou em software. O tratamento de exceções estruturados é ú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 capturar 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

O tratamento de exceção estruturado funciona com o Win32 para arquivos de origem C e C++. No entanto, ele não foi projetado especificamente para C++. Você pode garantir que seu código seja mais portátil usando o tratamento de exceções do C++. Além disso, o tratamento de exceções do C++ é mais flexível, pois pode lidar com exceções de qualquer tipo. Para programas C++, recomendamos que você use instruções nativas de manipulação de exceções C++: tente, capture e lance instruções.

A instrução composta após a __try cláusula é o corpo ou a seção protegida . A __except expressão também é conhecida como a expressão de filtro . Seu valor determina como a exceção é tratada. A instrução composta após a __except cláusula é o manipulador de exceção. 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 prossegue 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 __except cláusula.

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

    • EXCEPTION_CONTINUE_EXECUTION (-1) A exceção é ignorada. Continue a execução no ponto em que a exceção ocorreu.

    • EXCEPTION_CONTINUE_SEARCH (0) A exceção não é reconhecida. Continue pesquisando try-except na pilha por um manipulador, primeiro para conter instruções e, em seguida, para manipuladores com a próxima precedência mais alta.

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

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

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

Não é válido entrar em uma __try instrução, mas é válido saltar para fora de uma. O manipulador de exceção não será chamado se um processo for encerrado no meio da execução de uma try-except instrução.

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

A palavra-chave __leave

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

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

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

O tratamento de exceções estruturados fornece duas funções intrínsecas que estão disponíveis para uso com a try-except instrução: GetExceptionCode e GetExceptionInformation.

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

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

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

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

Você pode usar GetExceptionCode dentro do manipulador de exceção. No entanto, você só pode usar GetExceptionInformation dentro da expressão de filtro de exceção. As informações que ele aponta geralmente estão na pilha e não estão mais disponíveis quando o controle é transferido para o manipulador de exceção.

A função intrínseca AbnormalTermination está disponível em um manipulador de terminação. Ele retornará 0 se o corpo da instrução try-finally for encerrado sequencialmente. Em todos os outros casos, ele retorna 1.

<excpt.h> define alguns 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

Consulte também

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