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

Обработчики завершения не выполняются, если выполнение процесса или потока было прекращено независимо от того, было ли это инициировано самим процессом путем использования функций ExitProcess или ExitThread, или вызвано извне, например, инициировано вызовом функций TerminateProcess или TerminateThread из другого места в программе. Поэтому ни одна из этих функций не должна вызываться процессом или потоком внутри блоков try…except или try…finally.

Обратите также внимание, что выполнение функции библиотеки С exit или возврат из функции main приводят к выходу из процесса.

<p>SEH и обработка исключений в C++</p>

При обработке исключений в C++ используются ключевые слова catch и throw, а сам механизм исключений реализован с использованием SEH. Тем не менее, обработка исключений в C++ и SEH — это разные вещи. Их совместное применение требует внимательного обращения, поскольку обработчики исключений, написанные пользователем и сгенерированные C++, могут взаимодействовать между собой и приводить к нежелательным последствиям. Например, находящийся в стеке обработчик __except может перехватить исключение C++, в результате чего данное исключение так и не дойдет до обработчика C++.

Возможно и обратное, когда, например, обработчик C++ перехватит SEH-исключение, сгенерированное функцией RaiseException. Документация Microsoft рекомендует полностью отказаться от использования обработчиков Windows в программах на C++ и ограничиться применением в них только обработчиков исключений C++.

Кроме того, обработчики исключений или завершения Windows не осуществляют вызов деструкторов, что в ряде случаев необходимо для уничтожения экземпляров объектов C++.

<p>Пример: использование обработчиков завершения для повышения качества программ</p>

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

В программе toupper (программа 4.2) эти моменты иллюстрируются с привлечением идей, почерпнутых в программном коде предшествующих примеров. toupper обрабатывает несколько файлов, имена которых указываются в командной строке, переписывая их с преобразованием всех букв в верхний регистр. Имена преобразованных файлов получаются путем добавления префикса UC_ к исходным именам, и согласно "спецификации" программы запись поверх существующих файлов не производится. Преобразование файлов осуществляется в памяти машины, поэтому для каждого файла выделяется большая буферная область (достаточная для размещения всего файла). Кроме того, чтобы исключить любую возможность изменения файлов другими процессами, а также для того, чтобы вновь создаваемые выходные файлы строго соответствовали преобразованным входным файлам, оба вида файлов блокируются во время обработки. Понятно, что на каждой стадии обработки существует вероятность возникновения самых различных сбойных ситуаций, но в программе должна быть предусмотрена защита от подобных ошибок, и она должна располагать средствами, позволяющими ей восстановить свое нормальное состояние и попытаться обработать все остальные файлы, имена которых были указаны в командной строке. Программа 4.2 решает все эти задачи, обеспечивая разблокирование файлов во всех необходимых случаях без применения громоздкой логики операторов ветвления, к которым пришлось бы прибегнуть, если бы не были использованы средства SEH. Более подробные комментарии к программе содержатся в программном коде, находящемся на Web-сайте книги.

Программа 4.2. toupper: обработка файлов с восстановлением нормального состояния программы после сбоев

/* Глава 4. Команда toupper. */

/* Преобразование содержимое одного и более файлов с заменой всех букв на прописные. Имя выходного файла получается из имени входного файла добавлением к нему префикса UC_. */

#include "EvryThng.h"

int _tmain(DWORD argc, LPTSTR argv[]) {

 HANDLE hIn = INVALID_HANDLE_VALUE, hOut = INVALID_HANDLE_VALUE;

 DWORD FileSize, nXfer, iFile, j;

 CHAR OutFileName [256] = "", *pBuffer = NULL;

 OVERLAPPED ov = {0, 0, 0, 0, NULL}; /* Используется для блокирования файлов. */

 if (argc <= 1) ReportError(_T("Использование: toupper файлы"), 1, FALSE);

Перейти на страницу:

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

C++: базовый курс
C++: базовый курс

В этой книге описаны все основные средства языка С++ - от элементарных понятий до супервозможностей. После рассмотрения основ программирования на C++ (переменных, операторов, инструкций управления, функций, классов и объектов) читатель освоит такие более сложные средства языка, как механизм обработки исключительных ситуаций (исключений), шаблоны, пространства имен, динамическая идентификация типов, стандартная библиотека шаблонов (STL), а также познакомится с расширенным набором ключевых слов, используемым в .NET-программировании. Автор справочника - общепризнанный авторитет в области программирования на языках C и C++, Java и C# - включил в текст своей книги и советы программистам, которые позволят повысить эффективность их работы. Книга рассчитана на широкий круг читателей, желающих изучить язык программирования С++.

Герберт Шилдт

Программирование, программы, базы данных
Programming with POSIX® Threads
Programming with POSIX® Threads

With this practical book, you will attain a solid understanding of threads and will discover how to put this powerful mode of programming to work in real-world applications. The primary advantage of threaded programming is that it enables your applications to accomplish more than one task at the same time by using the number-crunching power of multiprocessor parallelism and by automatically exploiting I/O concurrency in your code, even on a single processor machine. The result: applications that are faster, more responsive to users, and often easier to maintain. Threaded programming is particularly well suited to network programming where it helps alleviate the bottleneck of slow network I/O. This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating System Interface) threads, commonly called Pthreads. Written for experienced C programmers, but assuming no previous knowledge of threads, the book explains basic concepts such as asynchronous programming, the lifecycle of a thread, and synchronization. You then move to more advanced topics such as attributes objects, thread-specific data, and realtime scheduling. An entire chapter is devoted to "real code," with a look at barriers, read/write locks, the work queue manager, and how to utilize existing libraries. In addition, the book tackles one of the thorniest problems faced by thread programmers-debugging-with valuable suggestions on how to avoid code errors and performance problems from the outset. Numerous annotated examples are used to illustrate real-world concepts. A Pthreads mini-reference and a look at future standardization are also included.

David Butenhof

Программирование, программы, базы данных