Оператор try-finally

Блок, относящийся только к системам Microsoft

Следующий синтаксис описывает оператор try-finally:

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

Грамматика

  • оператор-try-finally:
    __try составной-оператор

    __finally составной-оператор

Оператор try-finally является расширением Microsoft для языков C и С++ и позволяет целевым приложениям гарантировать выполнение кода очистки при прерывании выполнения блока кода. Очистка включает такие задачи, как отмена распределения памяти, закрытие файлов и освобождение их дескрипторов. Оператор try-finally особенно полезен для подпрограмм, в которых в нескольких местах выполняется проверка на наличие ошибок, способных вызвать преждевременное возвращение из подпрограммы.

Сопутствующую информацию и пример кода см. в разделе Оператор try-except. Дополнительные сведения о структурированной обработке исключений в общем см. в разделе Структурная обработка исключений. Дополнительные сведения об обработке исключений в управляемых приложениях см. в разделе Обработка исключений в /clr.

Примечание

Структурированная обработка исключений поддерживается в Win32 для исходных файлов как на C, так и на C++.Однако она не предназначена специально для C++.Для того чтобы ваш код лучше переносился, лучше использовать механизм обработки исключений языка C++.Кроме того, этот механизм отличается большей гибкостью, поскольку может обрабатывать исключения любого типа.В программах на языке C++ рекомендуется использовать механизм обработки исключений C++ (операторы try, catch и throw).

Составной оператор после предложения __try представляет собой защищенный раздел. Составной оператор после предложения __finally является обработчиком завершения. Такой обработчик определяет набор действий, выполняемых при выходе из защищенного раздела независимо от того, происходит ли выход в результате исключения (ненормальное завершение) или в результате стандартной передачи управления дальше (нормальное завершение).

Управление достигает оператора __try в процессе обычного последовательного выполнения (передачи управления дальше). Если элемент управления входит в __try, становится активным соответствующий обработчик. Если поток элементов управления достигает конца блока try, выполнение продолжается следующим образом.

  1. Вызывается обработчик завершения.

  2. По окончании работы обработчика завершения выполнение продолжается после оператора __finally. Независимо от того как завершается защищенный раздел (например, оператором goto выхода из защищенного тела или оператором return), обработчик завершения выполняется перед (before) выходом потока элементов управления из защищенного раздела.

    Оператор __finally не блокирует поиск соответствующего обработчика исключений.

Если исключение возникает в блоке __try, операционная система должна найти обработчик для исключения, либо программа завершится ошибкой. Если обработчик найден, любые и все блоки __finally выполняются и выполнение продолжается в обработчике.

Например, предположим, ряд вызовов функций связывает функцию А с функцией D, как показано на следующем рисунке. Каждая функция имеет один обработчик завершения. Если исключение создается в функции D и обрабатывается в функции А, обработчики завершения вызываются в том порядке, в котором система освобождает стек: D, C и B.

Порядок выполнения обработчиков завершения

Порядок выполнения обработчика завершения

Примечание

Поведение оператора try-finally отличается от некоторых других языков, поддерживающих использование оператора finally, например C#. Один оператор __try может иметь либо __finally, либо __except, но не оба. Если оба следует использовать одновременно, оператор try-except должен включать внутренней оператор try-finally. Правила,задающие время выполнения каждого блока, также различаются.

Ключевое слово __leave

Ключевое слово __leave может использоваться только в защищенном разделе оператора try-finally. Оно приводит к тому, что выполнение переходит в конец защищенного раздела. Выполнение продолжается с первого оператора в обработчике завершения.

Оператор goto может также выйти из защищенного раздела, однако в этом случае производительность снизится, поскольку будет вызвано освобождение стека. Оператор __leave более эффективен, поскольку не вызывает освобождение стека.

Аварийное завершение

Выход из оператора try-finally с помощью функции времени выполнения longjmp считается ненормальным завершением. Переход к оператору __try недопустим, но допустим выход из него. Все операторы __finally, которые активны между отправным пунктом (нормальным завершением блока __try) и точкой назначения (блоком __except, обрабатывающим исключение), должны быть запущены. Это называется "локальной раскруткой".

Если блок try по какой-либо причине завершается преждевременно (включая выход из блока), система выполняет связанный блок finally в рамках освобождения стека. В этих случаях функция AbnormalTermination возвращает значение TRUE, если вызывается из блока finally; в противном случае она возвращает значение FALSE.

Если в процессе выполнения оператора try-finally процесс удаляется, обработчик завершения не вызывается.

Завершение блока, относящегося только к системам Microsoft

См. также

Ссылки

Написание обработчика завершения

Структурированная обработка исключений (C/C++)

Ключевые слова в C++

Termination-Handler Syntax