Читаем Системное программирование в среде Windows полностью

Любое завершение выполнения программы по причинам, отличным от достижения конца try-блока и "проваливания вниз" или выполнения оператора __leave, считается аварийным завершением. Результатом выполнения оператора __leave является переход в конец блока __try и передача управления вниз по тексту программы, что намного эффективнее простого использования оператора goto, поскольку не требует разворачивания стека. Для определения того, каким образом завершилось выполнение try-блока, в обработчике завершения используется следующая функция: 

BOOL AbnormalTermination(VOID) 

При аварийном завершении выполнения блока эта функция возвращает значение TRUE, при нормальном — FALSE.

Примечание

Завершение будет считаться аварийным, даже если, например, последним оператором try-блока был оператор return.

<p>Выполнение обработчика завершения и выход из него</p>

Обработчик завершения, или блок __finally, выполняется в контексте блока или функции, работу которых он отслеживает. Управление может переходить от оператора завершения к следующему оператору. Существует и другая возможность, когда обработчик завершения выполняет оператор передачи управления (return, break, continue, goto, longjmp или __leave). Еще одной возможностью является выход из обработчика по причине возникновения исключения.

<p>Сочетание блоков finally и except</p>

Один 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) {

 /* Обработчик исключений. */

}

<p>Глобальное и локальное разворачивание стека</p>

Исключения и аварийные завершения вызывают глобальное разворачивание стека (global stack unwind) в поиске обработчика, как было показано на рис. 4.1. Предположим, например, что в отслеживаемом блоке примера, приведенного в конце предыдущего раздела, исключение возникает прежде, чем активизируются FP-исключения. Тогда перед обработчиком исключения в стеке могут находиться многочисленные обработчики завершения.

Вспомните, что структура стека является динамической, как показано на рис. 4.1, и что в стеке, наряду с другими данными, хранятся данные обработчиков исключений и завершения. Фактическое содержимое стека в любой момент времени зависит от следующих факторов:

• Статической структуры программных блоков.

•  Динамической структуры программы, отражаемой в последовательности открытых вызовов функций.

<p>Обработчики завершения: завершение процессов и потоков</p>
Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
1001 совет по обустройству компьютера
1001 совет по обустройству компьютера

В книге собраны и обобщены советы по решению различных проблем, которые рано или поздно возникают при эксплуатации как экономичных нетбуков, так и современных настольных моделей. Все приведенные рецепты опробованы на практике и разбиты по темам: аппаратные средства персональных компьютеров, компьютерные сети и подключение к Интернету, установка, настройка и ремонт ОС Windows, работа в Интернете, защита от вирусов. Рассмотрены не только готовые решения внезапно возникающих проблем, но и ответы на многие вопросы, которые возникают еще до покупки компьютера. Приведен необходимый минимум технических сведений, позволяющий принять осознанное решение.Компакт-диск прилагается только к печатному изданию книги.

Юрий Всеволодович Ревич

Программирование, программы, базы данных / Интернет / Компьютерное «железо» / ОС и Сети / Программное обеспечение / Книги по IT