На этом шаге мы рассмотрим механизмы использования отладочной информации.
В Delphi имеется возможность просматривать протокол сообщений о событиях, происходящих в процессе выполнения приложения в режиме отладки. Протокол этих сообщений Вы можете просмотреть, выполнив команду Event Log пункта меню View. Щелкнув в появившемся окне правой кнопкой мыши, можно сохранить этот протокол в файле, прокомментировать его, очистить.
Какие именно сообщения отображаются в этом окне, определяется настройкой отладчика. Можно влиять на содержимое этого окна с помощью функции OutputDebugString. Это функция API Windows, определенная следующим образом:
OutputDebugString(lpOutputString: PChar); ,
Например, если в текст программы вставить строку типа:
OutputDebugString(PChar('Проверка работы функции OutputDebugString'));,
Рис.1. Окно Event Log
Для встраивания отладочных средств в текст программы можно использовать процедуру Assert, которая объявлена следующим образом:
Procedure Assert(Expr: Boolean; const Msg: String); ,
Эту процедуру удобно применять для проверки истинности утверждений, которые должны быть истинны, но по каким-то причинам это не выполняется. Если проверяемое утверждение становится ложным, выполнение приложения прекращается, генерируется исключение EAssertionFailed и выдается сообщение об ошибке, в котором используется содержимое строки Msg. Если этот параметр в процедуре Assert отсутствует, то выдается стандартный текст сообщения. Если исключение EAssertionFailed не будет перехвачено, то оно вызовет прерывание работы программы с кодом 227.
Преимуществом процедуры Assert является то, что она работает только при включенной директиве проверки утверждений {$C+} или {$ASSERTIONS ON}. Они включены по умолчанию. Перед окончательным оформлением выполняемого модуля можно скомпилировать файл с директивой {$C-} или {$ASSERTIONS OFF}. В этом случае процедура Assert работать не будет.
Полезно включать в приложение отладочную печать, которая помогает следить за ходом выполнения процесса. Для этой цели удобно использовать компонент TMemo - многострочное окно редактирования. В него можно заносить отладочные данные и просматривать их в процессе выполнения приложения. Чтобы этот компонент не занимал место на форме, его можно выводить в отдельное окно. Приведем текст приложения, иллюстрирующего применение компонента TMemo (на форме расположите компоненты TLabel, TButton):
Рис.2. Внешний вид приложения
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Label1: TLabel; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} var FDebug: TForm;//Форма отладочного окна. Memo1:TMemo; A:Double=1; LDebug: Word=0;//Уровень отладки. procedure TForm1.FormCreate(Sender: TObject); begin //Установка уровня отладки. Можно закомментировать. LDebug:=1; If LDebug>0 Then Begin FDebug:=TForm.Create(Self);//Создание формы FDebug. FDebug.Caption:='Отладка';//Заголовок формы. Memo1:=TMemo.Create(FDebug);//Создание компонента TMemo. Memo1.Parent:=FDebug;//Определение родительского компонента. Memo1.ScrollBars:=ssVertical;//Строки прокрутки. Memo1.Align:=AlClient;//Выравнивание компонента TMemo. FDebug.Show;//Показ созданной формы. End; end; procedure TForm1.FormDestroy(Sender: TObject); begin If LDebug>0 Then FDebug.Release;//Уничтожение созданной формы. end; procedure TForm1.Button1Click(Sender: TObject); var //Процедура вычисления результата. i:Word; begin For i:=1 To 50 Do Begin If LDebug=1 Then //Отладочная печать при уровне = 1. Memo1.Lines.Add('A='+FloatToStr(A)+', i='+IntToStr(i)); A:=A*10000; End; Label1.Caption:=FloatToStr(A); end; end.
Результат работы приложения можно увидеть на рисунке 3:
Рис.3. Результат работы приложения
После отладки приложения достаточно закомментировать одну строку, чтобы отменить вывод отладочной информации.
Недостатком этого подхода является наличие отладочных операторов в окончательном варианте приложения. Чтобы этого избежать, можно воспользоваться директивами условной компиляции. В этом случае операторы отладки включаются в условную директиву следующим образом:
{$IFDEF Debug} <операторы отладки> {$ENDIF} .
Тогда, если в начале программы Вы поместите директиву {$DEFINE Debug} операторы отладки будут компилироваться и выполняться. Но если убрать ее, закомментировать или расположить после нее директиву {$UNDEF Debug}, то все операторы отладки исчезнут из окончательного кода приложения.
Практика показывает, что отладочные операторы обычно в ничтожной степени снижают эффективность работы приложения. Поэтому желательно оставлять отладочную печать в готовом приложении. Дело в том, что сложное приложение не может быть сделано без ошибок, которые могут проявляться через месяцы, годы работы у пользователя. В этом случае может помочь отладка. Включать ее можно, например, созданием текстового редактора, например Debug.txt, в котором указывается число (уровень отладки). В этом случае в приведенном ранее коде надо заменить оператор LDebug:=1 на:
If FileExists ('Debug.txt') Then Begin AssignFile(f, 'Debug.txt'); Reset(f); ReadLn(f,LDebug); End;
Var f:TextFile;
На следующем шаге мы начнем рассматривать средства отладки в среде Microsoft Visual C++.