__try {
/* Блок кода. */
} _finally {
/* Обработчик завершения (блок finally). */
}
Обработчик завершения выполняется всякий раз, когда в соответствии с логикой программы осуществляется выход из try-блока по одной из следующих причин:
• Достижение конца try-блока и "проваливание" в обработчик завершения.
• Выполнение одного из следующих операторов таким образом, что происходит выход за пределы блока:
return
break
goto [19] Возможно, это дело вкуса, — то ли индивидуального, то ли корпоративного, — но многие программисты никогда не пользуются оператором goto и избегают употребления оператора break, кроме случаев его совместного использования с операторами switch и иногда — в циклах, а также совместного использования с операторами continue. Те, кто мыслит трезво, не спешат определять свою позицию в этом отношении. Обработчики завершения и исключений могут решать многие из тех задач, для решения которых вам хотелось бы привлечь оператор goto и операторы, снабженные метками.
longjmp
continue
__leave [20] Этот оператор является специфическим для компилятора Microsoft С и предоставляет эффективный способ выхода из блока try…finally без аварийного завершения выполнения.
• Исключение.
Любое завершение выполнения программы по причинам, отличным от достижения конца try-блока и "проваливания вниз" или выполнения оператора __leave, считается аварийным завершением. Результатом выполнения оператора __leave является переход в конец блока __try и передача управления вниз по тексту программы, что намного эффективнее простого использования оператора goto, поскольку не требует разворачивания стека. Для определения того, каким образом завершилось выполнение try-блока, в обработчике завершения используется следующая функция:
BOOL AbnormalTermination(VOID)
При аварийном завершении выполнения блока эта функция возвращает значение TRUE, при нормальном — FALSE.
Примечание
Завершение будет считаться аварийным, даже если, например, последним оператором try-блока был оператор return.
Выполнение обработчика завершения и выход из него
Обработчик завершения, или блок __finally, выполняется в контексте блока или функции, работу которых он отслеживает. Управление может переходить от оператора завершения к следующему оператору. Существует и другая возможность, когда обработчик завершения выполняет оператор передачи управления (return, break, continue, goto, longjmp или __leave). Еще одной возможностью является выход из обработчика по причине возникновения исключения.
Сочетание блоков finally и except
Один try-блок может иметь только один блок finally или только один блок except, но не может иметь оба указанных блока одновременно. Поэтому нижеприведенный код вызовет появление ошибок на стадии компиляции.
__try {
/* Блок контролируемого кода. */
} __except (filter_expression) {
/* Блок обработчика исключений. */
} __finally {
/* Так делать нельзя! Это приведет к ошибке на стадии компиляции. */
}
Вместе с тем, допускается вложение одного блока в другой, что используется довольно часто. Нижеприведенный код является вполне работоспособным и обеспечивает гарантированное удаление временных файлов при выходе из цикла под управлением программы или в результате возникновения исключения. Эта методика оказывается удобной и в тех случаях, когда требуется обеспечить гарантированную отмену блокирования файлов, что будет использовано в программе 4.2. Кроме того, в коде имеется внутренний блок try…except, размещенный в том месте программы, где выполняются вычисления, в которых участвуют вещественные числа.
__try { /* Внешний блок try-except. */
while (…) __try { /* Внутренний блок try-finally. */
hFile = CreateFile(TempFile, …);
if(…) __try { /* Внутренний блок try-except. */
/* Разрешить FP-исключения. Выполнить вычисления. */
…
} __except(EXCEPTION_EXECUTE_HANDLER) {
… /* Обработать FP-исключение. */
_clearfp();
}
… /* Обработка исключений, не являющихся FP-исключениями. /*
} __finally { /* Конец цикла while. */
/* Выполняется на КАЖДОЙ итерации цикла. */
CloseHandle(hFile);
DeleteFile(TempFile);
}
} __except ( filter-expression) {
/* Обработчик исключений. */
}
Глобальное и локальное разворачивание стека
Читать дальше