Сообщений 5    Оценка 151 [+0/-1]         Оценить  
Система Orphus

Классы CErrCodeMsg и CLastErrCodeMsg

Автор: Игорь Вартанов
Опубликовано: 24.09.2001
Исправлено: 15.04.2009
Версия текста: 1.1.1

CErrCodeMsg
CLastErrCodeMsg
Изменения
v1.03

Загрузить классы CErrCodeMsg и CLastErrCodeMsg

Всем нам известны ситуации, когда в приложении, находящемся в стадии разработки или отладки, вы хотели бы получить не код ошибки (возможно вам вовсе незнакомый), а строку осмысленного (ну, или вроде того :-)) текста, описывающего произошедшую ошибку вызова некоей функции. Рецепты для подобных ситуаций, в принципе, известны: либо вручную ввести код ошибки в утилиту Error Lookup, либо вставлять в код вызовы FormatMessage(). Часто наиболее приемлемым вариантом бывает именно последний, но и он не слишком удобен, поскольку вызов FormatMessage() достаточно громоздок в смысле большого количества писанины, использования длинных дефайнов для флагов (и сопряженной с этим необходимости помнить точное их написание). Причем использование флага FORMAT_MESSAGE_ALLOCATE_BUFFER (само по себе удобное и полезное) приводит к опасности забыть освободить память, выделенную для нас системой.

CErrCodeMsg

Класс CErrCodeMsg выполняет роль "обертки" вокруг системной функции FormatMessage(), т.е. предоставляет программисту простой и удобный интерфейс для получения текстовых строк описания кодов завершения и ошибок, возвращаемых системой. Инкапсуляция возможностей FormatMessage() выполнена неполностью, но реализована наиболее полезная на взгляд автора возможность сообщить системе о том, что ей необходимо самостоятельно выделить буфер для хранения возвращаемой строки. Кроме того, предоставлена возможность явно задать язык, для которого должна быть сформирована строка описания, хотя это сделано скорее из соображений возможного дальнейшего развития класса. Ну и, разумеется, класс самостоятельно реализует возврат памяти, выделенной под буфер.

Бинарный оператор operator=() и оператор приведения типа operator DWORD() позволяют экземпляру класса вести себя подобно переменной типа DWORD в выражениях присваивания.

При создании объекта класса строка описания кода не формируется и память под нее не отводится до первого вызова метода GetString(), в котором, собственно, и производится вызов FormatMessage().

HRESULT hr = CoCreateInstance( . . . );
CErrCodeMsg err( hr );
MessageBox(NULL, err.GetString(), "HRESULT", MB_OK);
. . .
err = CoCreateInstance( . . . );
hr = err;
// или эквивалентно этому
hr = err.GetCode();

В случае использования объекта класса в консольном приложении класс предоставляет метод GetOemString(), возвращающий строку описания в OEM-кодировке. Опять таки, класс самостоятельно выделяет память под OEM-строку и, при разрушении объекта, самостоятельно ее освобождает.

ПРИМЕЧАНИЕ
Использование класса в консольных приложениях ведет к некоторым накладным расходам, поскольку выделяется память и под ANSI-, и под OEM-строки.

В случае, если программист создал объект класса на стеке и считает, что слишком долго ждать, когда объект при разрушении самостоятельно освободит память, зарезервированную под строки описания, в его распоряжении всегда имеется метод Deallocate(). Кстати, при присвоении объекту нового кода ошибки класс освобождает зарезервированную под строки память, следовательно, вместо вызова Deallocate() можно выполнить:

CErrCodeMsg err( hr );
. . .
err = 0;
// если объект больше не используется,
// это еквивалентно следующему:
// err.Deallocate(); 

Если нет необходимости хранить долгое время код ошибки, а нужно лишь получить строку сообщения, то проще всего воспользоваться следующим методом:

MessageBox( NULL, CErrCodeMsg( hr ).GetString(), "Error", MB_OK );

Существует возможность для программиста самостоятельно выделить буфер для хранения строки и передать его объекту.

const int сnSize = 1024;
char buf[ сnSize ] = {0};
CErrCodeMsg err( hr, FORMAT_MESSAGE_FROM_SYSTEM, сnSize, buf );

В этом случае класс не управляет временем жизни буфера, предполагая, что программист сам выполнит эту нелегкую миссию.

CLastErrCodeMsg

Есть специальный разряд кодов ошибки, с которыми знакомы практически все Windows-программисты - это так называемый "код последней ошибки", возвращаемый функцией GetLastError(). Соответственно, класс CLastErrCodeMsg (наследник от CErrCodeMsg) предназначен именно для работы с кодом последней ошибки. При конструировании объекта конструктор класса самостоятельно выполняет вызов GetLastError() и заносит его в закрытую переменную класса.

if( INVALID_HANDLE_VALUE == CreateFile(...) )
{
    CLastErrCodeMsg lastErr; // получаем код последней ошибки!
    char szErrCodeNum[16];
    wsprintf( szErrCodeNum, "%d", (DWORD)lastErr );
    MessageBox( NULL, lastErr.GetString(), szErrCodeNum, MB_OK );
    . . .
}

В остальном объект ведет себя абсолютно идентично объектам класса CErrCodeMsg.

Изменения

v1.03


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
    Сообщений 5    Оценка 151 [+0/-1]         Оценить