Книга: Системное программирование в среде Windows
Пример: использование функции фильтра
Разделы на этой странице:
Пример: использование функции фильтра
Программа 4.3 представляет собой каркас программы, иллюстрирующей обработку исключений и завершения выполнения, в которой используется функция фильтра. Программа предлагает пользователю указать тип исключения, после чего продолжает работу для генерации исключения. Функция фильтра обрабатывает различные типы исключений по-разному; выбор вариантов, предусмотренных в программе, был совершенно произвольным и определялся исключительно целями демонстрации. В частности, программа обнаруживает попытки обращения к недоступным областям памяти, предоставляя адреса виртуальной памяти, по которым производилось такое обращение.
Блок __finally восстанавливает состояние маски FP-исключений. Совершенно очевидно, что восстановление состояния маски в данном случае, когда процесс уже должен завершаться, особого значения не имеет, но эта методика пригодится нам впоследствии, когда мы будем использовать ее на стадии завершения выполнения потока. Вообще говоря, процесс должен восстанавливать и системные ресурсы, например, удалять временные файлы, освобождать ресурсы синхронизации (глава 8) и отменять блокирование файлов (главы 3 и 6). Функция фильтра представлена в программе 4.4.
Данный пример не иллюстрирует обработку исключений, которые могут возникать при распределении памяти; эти исключения мы начнем интенсивно использовать в главе 5.
Программа 4.3. Exception: обработка исключений и завершения выполнения
#include "EvryThng.h"
#include <float.h>
DWORD Filter(LPEXCEPTION_POINTERS, LPDWORD);
double x = 1.0, у = 0.0;
int _tmain(int argc, LPTSTR argv[]) {
DWORD ECatgry, i = 0, ix, iy = 0;
LPDWORD pNull = NULL;
BOOL Done = FALSE;
DWORD FPOld, FPNew;
FPOld = _controlfp(0, 0); /* Сохранить старую управляющую маску. */
/* Разрешить FP-исключения. */
FPNew = FPOld & ~(EM_OVERFLOW | EM_UNDERFLOW | EM_INEXACT | EM_ZERODIVIDE | EM_DENORMAL | EM_INVALID);
_controlfp(FPNew, MCW_EM);
while (!Done) _try { /* Блок try-finally. */
_tprintf(_T("Введите тип исключения: "));
_tprintf(_T(" 1: Mem, 2: Int, 3: Flt 4: User 5: __leave "));
_tscanf(_T("%d"), &i);
__try { /* Блок try-except. */
switch (i) {
case 1: /* Исключение при обращении к памяти. */
ix = *pNull;
*pNull = 5;
break;
case 2: /* Исключение при выполнении арифметических операций над целыми числами. */
ix = ix / iy;
break;
case 3: /* FP-исключение. */
x = x / у;
_tprintf(_T("x = %20en"), x);
break;
case 4: /* Пользовательское исключение. */
ReportException(_T("Пользовательское исключение"), 1);
break;
case 5: /* Использовать оператор _leave для завершения выполнения.*/
__leave;
default:
Done = TRUE;
}
} /* Конец внутреннего блока __try. */
__except(Filter(GetExceptionInformation(), &ECatgry)) {
switch(ECatgry) {
case 0:
_tprintf(_T("Неизвестное исключениеn"));
break;
case 1:
_tprintf(_T("Исключение при обращении к памятиn"));
continue;
case 2:
_tprintf(_T("Исключение при выполнении арифметических операций над целыми числами n"));
break;
case 3:
_tprintf(_Т("FР-исключениеn"));
_clearfp();
break;
case 10:
_tprintf(_T("Пользовательское исключениеn"));
break;
default:
_tprintf(_T("Неизвестное исключениеn"));
break;
} /* Конец оператора switch. */
_tprintf(_Т("Конец обработчикаn"));
}
/* Конец блока try-except. */
} /* Конец цикла while – ниже находится обработчик завершения. */
__finally { /* Это часть цикла while. */
_tprintf(_T("Аварийное завершение?: %dn"),
AbnormalTermination());
}
_controlfp(FPOld, 0xFFFFFFFF); /* Восстановить старую FP-маску.*/
return 0;
}
Программа 4.4 представляет функцию фильтра, используемую в программе 4.3. Эта функция просто проверяет и классифицирует различные возможные значения кодов исключений. В программном коде, размещенном на Web-сайте книги, проверяется каждое из возможных значений, в то время как приведенная ниже функция осуществляет проверку лишь тех из них, которые нужны для тестовой программы.
Программа 4.4. Функция Filter
static DWORD Filter(LPEXCEPTION_POINTERS pExP, LPDWORD ECatgry)
/* Классификация исключений и выбор соответствующего действия. */
{
DWORD ExCode, ReadWrite, VirtAddr;
ExCode = pExP->ExceptionRecord->ExceptionCode;
_tprintf(_T("Filter. ExCode:. %xn"), ExCode);
if ((0x20000000 & ExCode) != 0) { /* Пользовательское исключение. */
*ECatgry =10;
return EXCEPTION_EXECUTE_HANDLER;
}
switch (ExCode) {
case EXCEPTION_ACCESS_VIOLATION:
ReadWrite = /* Операция чтения или записи? */
pExP->ExceptionRecord->ExceptionInformation[0];
VirtAddr = /* Адрес сбоя в виртуальный памяти. */
pExP->ExceptionRecord->ExceptionInformation [1];
_tprintf(_T("Нарушение доступа. Чтение/запись: %d. Адрес: %хn"), ReadWrite, VirtAddr);
*ECatgry = 1;
return EXCEPTION_EXECUTE_HANDLER;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
case EXCEPTION_INT_OVERFLOW:
*ECatgry = 2;
return EXCEPTION_EXECUTE_HANDLER;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_OVERFLOW:
_tprintf(_T("FP-исключение — слишком большое значение.n"));
*ECatgry = 3;
_clearfp();
return (DWORD)EXCEPTION_EXECUTE_HANDLER;
default:
*ECatgry = 0;
return EXCEPTION_CONTINUE_SEARCH;
}
}
- Исключения и обработчики исключений
- Исключения, возникающие при выполнении операций над числами с плавающей точкой
- Ошибки и исключения
- Пример: обработка ошибок как исключений
- Обработчики завершения
- Пример: использование обработчиков завершения для повышения качества программ
- Пример: использование функции фильтра
- Обработчики управляющих сигналов консоли
- Пример: обработчик управляющих сигналов консоли
- Векторная обработка исключений
- Резюме
- Упражнения
- Пример установочного скрипта
- Пример из практики
- Восстановление с использованием инструмента gbak
- Типы страниц и их использование
- ПРИМЕР ПРОСТОЙ ПРОГРАММЫ НА ЯЗЫКЕ СИ
- Использование констант
- Аргументы функции в Python
- Использование переменной окружения ISC_PATH
- Использование сервера Yaffil внутри процесса
- Использование CAST() с типами дата
- 3. Функции
- Примеры получения статистики