Страница 6 из 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.
|