Пример: обработка ошибок

Пример: обработка ошибок

В программе 1.2 было продемонстрировано использование лишь самых примитивных средств обработки ошибок, а именно, получение номера ошибки в переменной типа DWORD с помощью функции GetLastError. Вызов функции, а не просто получение глобального номера ошибки, как это делается при помощи функции UNIX errno, гарантирует уникальную идентификацию системных ошибок для каждого из потоков (глава 7), использующих разделяемую область хранения данных.

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

В программе 2.2 представлена полезная универсальная функция ReportError, предназначенная для обработки ошибок и по своим возможностям аналогичная входящей в состав библиотеки С функции perror, а также описанным в [40] функциям err_sys и err_ret. Функция ReportError передает в выходной буфер сообщение в виде, определяемом первым аргументом, и либо прекращает выполнение с кодом выхода по ошибке, либо осуществляет обычный возврат управления, в зависимости от значения второго аргумента. Третий аргумент определяет, должны ли отображаться системные сообщения об ошибках.

Обратите внимание на аргументы функции FormatMessage. В качестве одного из параметров используется значение, возвращаемое функцией GetLastError, a на необходимость генерации сообщения системой указывает флаг. Сгенерированное сообщение сохраняется в буфере, выделяемом функцией, а соответствующий адрес возвращается в параметре. Имеются также другие параметры, для которых указаны значения по умолчанию. Язык сообщений может быть задан как во время компиляции, так и во время выполнения. В этой книге функция Format-Message далее нигде не используется, поэтому никаких дополнительных пояснений относительно нее в тексте не дается. 

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

В программе 2.2 вводится заголовочный файл EvryThng.h. Как следует из самого его названия, этот файл включает в себя файлы <windows.h>, Envirmnt.h и все остальные заголовочные файлы, которые были явно указаны в программе 2.1. Кроме того, в нем описаны такие обычно используемые функции, как PrintMsg, PrintStrings и ReportError. Во всех остальных примерах будет использоваться только этот заголовочный файл, листинг которого приведен в приложении А.

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

Программа 2.2. Функция Report Error, предназначенная для вывода сообщений об ошибках при выполнении системных вызовов 

#include "EvryThng.h"

VOID ReportError(LPCTSTR UserMessage, DWORD ExitCode, BOOL PrintErrorMsg)

/* Универсальная функция для вывода сообщений о системных ошибках. */

{

 DWORD eMsgLen, LastErr = GetLastError();

 LPTSTR lpvSysMsg;

 HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE);

 PrintMsg(hStdErr, UserMessage);

 if (PrintErrorMsg) {

  eMsgLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, LastErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpvSysMsg, 0, NULL);

  PrintStrings (hStdErr, _T(" "), lpvSysMsg, _T(" "), NULL);

  /* Освободить блок памяти, содержащий сообщение об ошибке. */

  HeapFree(GetProcessHeap(), 0, lpvSysMsg); /* См. гл. 5. */

 }

 if (ExitCode > 0) ExitProcess (ExitCode);

 else return;