Комплексный контроль за качеством кода
Страница 6. Пример модуля с функциями комплексной обработки ошибок


7. Пример модуля с функциями комплексной обработки ошибок

////////////////////////////////////////////////////////////////////////////////
// ATSTest - иллюстрация комплексной обработки исключений
// (c) Николай Мазуркин
// _____________________________________________________________________________
// Процедуры обработки фатальных ошибок
////////////////////////////////////////////////////////////////////////////////

unit ATSAssert;

interface

uses Windows, Messages, SysUtils, ActiveX, Forms; 

Объявления деклараций используемых функций

Объявляется перечень и формат функций для комлексного контроля за качеством кода. 
////////////////////////////////////////////////////////////////////////////////
// Процедуры обработки фатальных ситуаций
////////////////////////////////////////////////////////////////////////////////
procedure AssertMsg(Condition: Boolean; const Mark: string);
procedure AssertWin32(Condition: Boolean; const Mark: string);
function AssertInternal(const Mark: string): TObject;
procedure HandleError(const Msg: string);

implementation

////////////////////////////////////////////////////////////////////////////////
// Utils
// _____________________________________________________________________________
// Процедуры обработки фатальных ситуаций
//////////////////////////////////////////////////////////////////////////////// 

Глобальный обработчик исключений

Глобальный обработчик исключений устанавливает процедуру обработки на событие Application.OnException. Это позволяет перехватывать все исключения не пойманные конструкцией try-except-AssertInternal-end. Хотя таких непойманных исключений быть не должно, лучше все-таки поставить на них обработчик.

Если вы пишите библиотеку DLL в таком обработчике нет необходимости, так как все непойманные исключения будут обрабатывать в EXE-модуле.

////////////////////////////////////////////////////////////////////////////////
// TExceptHandler
// _____________________________________________________________________________
// Глобальный обработчик исключений
////////////////////////////////////////////////////////////////////////////////
type
TExceptHandler = class (TObject)
procedure OnException(Sender: TObject; E: Exception);
end;

var
ExceptHandler : TExceptHandler;

////////////////////////////////////////////////////////////////////////////////
// Обработка исключений
////////////////////////////////////////////////////////////////////////////////
procedure TExceptHandler.OnException(Sender: TObject; E: Exception);
begin
HandleError(PChar(E.Message));
end; 

Основная процедура обработки ошибок

Основная процедура обработки ошибок. Формирует и выводит сообщение, записывает его в посмертный лог и закрывает программу. Если вы пишете библиотеку DLL, то для каждой библиотеки можете добавить к сообщению свой дополнительный префикс, например 'A', 'B', 'C' и т.д. Это поможет быстро определить в каком модуле произошла ошибка. 
////////////////////////////////////////////////////////////////////////////////
// Обработка ошибочной ситуации
////////////////////////////////////////////////////////////////////////////////
procedure HandleError(const Msg: string);
var
DeadFile : TextFile;
DeadName : string;
ErrorMsg : string;
begin
// Формируем сообщение
ErrorMsg := Msg + #13#13;
// Если это исключение, то добавим его тип и адрес
if ExceptObject <> nil then
ErrorMsg := ErrorMsg + Format('Исключение типа %s, адрес 0x%8.8x'#13#13,
[ExceptObject.ClassName, DWord(ExceptAddr)]
);
ErrorMsg := ErrorMsg + 'Выполнение программы будет прекращено.';
// Показываем диалог
MessageBox(0, PChar(ErrorMsg),
'Фатальная ошибка', MB_OK+MB_ICONWARNING+MB_APPLMODAL+MB_SETFOREGROUND+MB_TOPMOST);
// Генерируем уникальное имя файла
SetLength(DeadName, MAX_PATH+10);
GetTempFileName(PChar(ExtractFilePath(ParamStr(0))), 'err', 0, @DeadName[1]);
// Записываем ошибку в посмертный лог - на случай если пользователь не догадается
// записать код ошибки и сообщение.
AssignFile(DeadFile, DeadName);
ReWrite(DeadFile);
WriteLn(DeadFile, ErrorMsg);
CloseFile(DeadFile);
// Немедленно закрываем процесс
ExitProcess(1);
end; 

Альтернативная процедура Assert

////////////////////////////////////////////////////////////////////////////////
// Проверка выполнимости условия
////////////////////////////////////////////////////////////////////////////////
procedure AssertMsg(Condition: Boolean; const Mark: string);
begin
// Если условие выполняется, то выходим сразу
if Condition then Exit;
// Обрабатываем возникшую ошибку
HandleError('Фатальная ошибка '+Mark);
end; 

Альтернативная процедура Assert для API-функций

////////////////////////////////////////////////////////////////////////////////
// Проверка выполнимости API-функции
////////////////////////////////////////////////////////////////////////////////
procedure AssertWin32(Condition: Boolean; const Mark: string);
var
ErrorMsg : string;
begin
// Если условие выполняется, то выходим
if Condition then Exit;
// Получаем сообщение об ошибке
ErrorMsg := SysErrorMessage(GetLastError);
// Обрабатываем возникшую ошибку
HandleError('Фатальная ошибка '+Mark+#13#13+ErrorMsg);
end; 

Функция для тотального контроля исключений

Функция для перехвата исключений от VCL и неудачных обращений к памяти. Добаляет к тексту исключения уникальную метку и генерирует ошибку. 
////////////////////////////////////////////////////////////////////////////////
// Генерация фатального исключения
////////////////////////////////////////////////////////////////////////////////
function AssertInternal(const Mark: string): TObject;
begin
// Проверяем тип сгенерированного исключения и обрабатываем возникшую ошибку
if ExceptObject is Exception then
HandleError('Фатальная ошибка '+Mark+#13#13+PChar(Exception(ExceptObject).Message))
else
HandleError('Фатальная ошибка '+Mark);
// Следующая строчка никогда не выполнится, она нужна для успокоения компилятора
Result := nil;
end; 

Инициализация модуля

Создание и настройка глобального обработчика исключения на событии TApplication.OnException. 
////////////////////////////////////////////////////////////////////////////////
// Автоматическое создание глобального обработчика исключения
////////////////////////////////////////////////////////////////////////////////
initialization
ExceptHandler := TExceptHandler.Create;
Application.OnException := ExceptHandler.OnException;

end.
 
« Предыдущая статья   Следующая статья »