Джонсон Харт - Системное программирование в среде Windows
- Название:Системное программирование в среде Windows
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2005
- Город:Москва • Санкт-Петербург • Киев
- ISBN:5-8459-0879-5
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Джонсон Харт - Системное программирование в среде Windows краткое содержание
Эта книга посвящена вопросам разработки приложений с использованием интерфейса прикладного программирования операционных систем компании Microsoft (Windows 9х, Windows XP, Windows 2000 и Windows Server 2003). Основное внимание уделяется базовым системным службам, включая управление файловой системой, процессами и потоками, взаимодействие между процессами, сетевое программирование и синхронизацию. Рассматривается методика переноса приложений, написанных в среде Win32, в среду Win64. Подробно описываются все аспекты системы безопасности Windows и ее практического применения. Изобилие реальных примеров, доступных также и на Web-сайте книги, существенно упрощает усвоение материала.
Книга ориентирована на разработчиков и программистов, как высокой квалификации, так и начинающих, а также будет полезна для студентов соответствующих специальностей.
Системное программирование в среде Windows - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Обработчики завершения служат в основном тем же целям, что и обработчики исключений, но выполняются, когда поток покидает блок в результате нормального выполнения программы, а также когда возникает исключение. С другой стороны, обработчик завершения не может распознавать исключения.
Обработчик завершения строится с использования ключевого слова __finally в операторе try…finally. Структура этого оператора аналогична структуре оператора try…finally, но в ней отсутствует выражение фильтра. Как и обработчики исключений, обработчики завершения предоставляют удобные возможности для закрытия дескрипторов, освобождения ресурсов, восстановления масок и выполнения иных действий, направленных на восстановление известного состояния системы после выхода из блока. Например, программа может выполнять операторы return внутри блока, оставляя всю работу по "уборке мусора" обработчику завершения. Благодаря этому отпадает необходимость во включении кода очистки в код самого блока или переходе к коду очистки при помощи оператора goto.
__try {
/* Блок кода. */
} _finally {
/* Обработчик завершения (блок finally). */
}
Выход из try-блока
Обработчик завершения выполняется всякий раз, когда в соответствии с логикой программы осуществляется выход из 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) {
/* Обработчик исключений. */
}
Глобальное и локальное разворачивание стека
Исключения и аварийные завершения вызывают глобальное разворачивание стека (global stack unwind) в поиске обработчика, как было показано на рис. 4.1. Предположим, например, что в отслеживаемом блоке примера, приведенного в конце предыдущего раздела, исключение возникает прежде, чем активизируются FP-исключения. Тогда перед обработчиком исключения в стеке могут находиться многочисленные обработчики завершения.
Вспомните, что структура стека является динамической, как показано на рис. 4.1, и что в стеке, наряду с другими данными, хранятся данные обработчиков исключений и завершения. Фактическое содержимое стека в любой момент времени зависит от следующих факторов:
• Статической структуры программных блоков.
• Динамической структуры программы, отражаемой в последовательности открытых вызовов функций.
Обработчики завершения: завершение процессов и потоков
Обработчики завершения не выполняются, если выполнение процесса или потока было прекращено независимо от того, было ли это инициировано самим процессом путем использования функций ExitProcess или ExitThread, или вызвано извне, например, инициировано вызовом функций TerminateProcess или TerminateThread из другого места в программе. Поэтому ни одна из этих функций не должна вызываться процессом или потоком внутри блоков try…except или try…finally.
Читать дальшеИнтервал:
Закладка: