Описание наиболее значимых полей этой структуры
приведено ниже:
ExceptionCode – тип исключения.
ExceptionFlags – флаг исключения.
ExceptionAddress – адрес участка кода, где возникло
исключение.
Второй параметр функции содержит в себе указатель на
структуру PEXCEPTION_REGISTRATION. Ее описание и назначение было приведено
выше.
Третий параметр указывает на переменную типа PCONTEXT
и несет информацию о состоянии регистров во время исключения.
Таким образом, механизм обработки исключений
становится более или менее ясным, т.е. когда в приложении возникает исключение, операционная система берет текущий указатель по адресу fs:[0] и просматривает
список обработчиков в поисках нужного обработчика исключения. Если обработчик
найден, она передает ему управление. В противном случае операционная система
выполняет свой обработчик, который вызывает функцию UnhandledExceptionFilter.
Значит, для получения управления в случае возникновения необработанного
исключения, нужно зарегистрировать свой обработчик и расположить его в вершине
этого списка. Но мир программирования не был бы таким интересным, если бы все
было так просто! Давайте пройдем дальше и посмотрим, что происходит во время
старта приложения, и какую роль в обработке исключений играет
runtime-библиотека.
Старт приложения и инициализация runtime
Когда операционная система загружает приложение, она
считывает содержимое файла с диска в память, загружает все необходимые для
работы приложения внешние библиотеки и инициализирует таблицу импорта адресами
реальных функций. После этого загрузчик передает управление на точку входа
приложения. В случае С++-приложений, написанных с использованием Microsoft
Visual Studio 6.0 (7.x, 8.0), управление передается функции WinMainCRTStartup
или wWinMainCRTStartup, в зависимости от версии runtime-библиотеки – UNICODE
или Multi-Byte Character Set (MBCS). Эта функция подготавливает приложение к
работе, инициализирует runtime, выполняет конструкторы всех статических
переменных и передает управление на точку входа, определенную разработчиком.
Если внимательно рассмотреть эту функцию, можно увидеть, что инициализация
пользовательских статических переменных и передача управления на
пользовательскую точку входа осуществляется внутри блока __try … __except.
Углубившись в исследование фильтра исключений runtime-библиотеки, я обнаружил, что в случае возникновения необработанного исключения он вызывает функцию
UnhandledExceptionFilter.
Функция UnhandledExceptionFilter находится в
библиотеке kernel32.dll и присутствует в Windows, начиная с версии Windows
95/NT. Назначение этой функции, как видно из названия - обработка
необработанных исключений и завершение приложения. В зависимости от того, как
запущено приложение, UnhandledExceptionFilter ведет себя по-разному. Так, если
приложение находится под отладкой, она передает управление отладчику, в
противном случае она выводит диалоговое окно «Application Error». Значит, для
обработки необработанных исключений, следует установить свой обработчик не на
вершину списка обработчиков, как казалось раньше, а перед обработчиком Runtime
библиотеки.
Установка обработчика верхнего уровня
Давайте немного отдохнем и суммируем все сказанное
выше. SEH – это системный сервис, в котором унифицирован механизм обработки
исключений, все обработчики текущего потока регистрируются в списке регистрации
обработчиков исключений. Если в функции встречается конструкция __try …
__except, то создается код, который регистрирует новый обработчик исключения и
помещает информацию о нем в стек. Во время завершения функции (а точнее, после
того, как управление вышло из секции __try), функция разрегистрирует
обработчик. Значит, если к текущему моменту в стеке находится три функции, каждая из которых установила свой обработчик исключения, то в списке
обработчиков исключения должно находиться по крайней мере три обработчика, а в
стеке должны находиться три записи об обработчиках исключений. Информация о
текущем обработчике доступна по адресу fs:[0]. Runtime-библиотека регистрирует
свой обработчик исключений, который (если исключение не обрабатывается приложением)
вызывает функцию UnhandledExceptionFilter, после чего приложение завершается с
выводом диалогового окна «Application Error».
Теперь настало время написать код, который бы
использовал сказанное выше и подтвердил правильность наших суждений. Давайте
напишем простую функцию, которая бы пробегала по всем зарегистрированным
обработчикам и выводила информацию о них на экран. Код функции приведен ниже:
void zWalkThroughSEH()
{
_EXCEPTION_REGISTRATION *
pVCExcRec;
__asm mov eax, FS:[0]
__asm mov [pVCExcRec], EAX
// Перебираем блоки в связанном списке. 0xFFFFFFFF означает конец списка.
printf("Exception
Registration chain:n");
while (0xFFFFFFFF !=
(unsigned)(UINT_PTR)pVCExcRec)
Рекомендуем скачать другие рефераты по теме: онегин сочинение, реферат підприємство.