Instrução try-finally

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

Sintaxe

A seguinte sintaxe descreve a instrução try-finally:

    // . . .
    __try {
        // guarded code
    }
    __finally {
        // termination code
    }
    // . . .

Gramática

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

A instrução try-finally é uma extensão da Microsoft para as linguagens C e C++ que permite que aplicativos de destino garantam a execução do código de limpeza quando a execução de um bloco de códigos é interrompida. A limpeza consiste em tarefas como desalocar memória, fechar arquivos e liberar identificadores de arquivos. A instrução try-finally é especialmente útil para rotinas que têm vários locais onde uma verificação é feita para um erro que pode causar o retorno prematuro da rotina.

Para informações relacionadas e um exemplo de código, confira Instrução try-except. Para mais informações sobre o tratamento de exceções estruturado em geral, confira Tratamento de exceções estruturado. Para mais informações sobre como lidar com exceções em aplicativos gerenciados com C++/CLI, confira Tratamento de exceção em /clr.

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++, é recomendável usar o mecanismo de manipulação de exceção de C++ (instruções try, catch e throw).

A instrução composta após a cláusula __try é a seção protegida. A instrução composta após a cláusula __finally é o manipulador de término. O manipulador especifica um conjunto de ações que são executadas quando você sai da seção protegida, independentemente de a saída da seção protegida ser realizada por uma exceção (término anormal) ou por queda padrão (término normal).

O controle atinge a instrução __try em uma execução sequencial simples (queda). Quando o controle entra em __try, seu manipulador associado fica ativo. Se o fluxo de controle chegar ao fim do bloco try, a execução continuará da seguinte maneira:

  1. O manipulador de término é invocado.

  2. Quando o manipulador de término é concluído, a execução continua após a instrução __finally. Independentemente de como a seção protegida é encerrada (por exemplo, por meio de um goto fora do corpo protegido ou de uma instrução return), o manipulador de encerramento é executado antes que o fluxo de controle sai da seção protegida.

    Uma instrução __finally não bloqueia a procura por um manipulador de exceção apropriado.

Se ocorrer uma exceção no __try bloco, o sistema operacional deverá localizar um manipulador para a exceção ou o programa falhará. Se um manipulador for encontrado, todos os blocos __finally serão executados e a execução será retomada no manipulador.

Por exemplo, imagine que uma série de chamadas de função vincula a função A à função D, conforme mostrado na figura a seguir. Cada função tem um manipulador de encerramento. Se uma exceção é gerada na função D e tratada na A, os manipuladores de encerramento são chamados nessa ordem à medida que o sistema desenrola a pilha: D, C, B.

Diagram of the order of termination handler execution.

O diagrama começa com a função A, que chama a função B, que chama a função C, que chama a função D. A função D gera uma exceção. Os manipuladores de terminação são então chamados nesta ordem: manipulador de terminação de D, C, B, e A manipula a exceção.

Ordem de execução do manipulador de terminação

Observação

O comportamento de try-finally é diferente do de outras linguagens que oferecem suporte ao uso de finally, como C#. Um __try pode ter __finally ou __except, mas não ambos. Se ambos devem ser usados juntos, uma instrução try-except externa deve incluir a instrução interna try-finally. As regras que especificam quando cada bloco é executado também são diferentes.

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

A palavra-chave __leave

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

Uma instrução goto também pode sair da seção protegida, mas prejudica o desempenho porque invoca o desenrolamento da pilha. A instrução __leave é mais eficiente porque não causa o desenrolamento da pilha.

encerramento anormal

Sair de uma instrução try-finally usando a função de tempo de execução longjmp é considerado um encerramento anormal. Não é permitido ir para uma instrução __try, mas é permitido sair de uma. Todas as instruções __finally que estão ativas entre o ponto de partida (encerramento normal do bloco __try) e o destino (o bloco __except que trata a exceção) devem ser executadas. Isso se chama desenrolamento local.

Se um bloco __try é encerrado prematuramente por qualquer motivo, incluindo uma saída do bloco, o sistema executa o bloco __finally associado como parte do processo de desenrolamento da pilha. Nesses casos, a função AbnormalTermination retorna true se chamada de dentro do bloco __finally; caso contrário, ela retorna false.

O manipulador de encerramento não é chamado se um processo é interrompido no meio da execução de uma instrução try-finally.

FIM Específico da Microsoft

Confira também

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