Шаг 34.
Средства отладки в Borland Delphi 4.0. Встраивание отладочных средств в текст программы

    На этом шаге мы рассмотрим механизмы использования отладочной информации.

    В Delphi имеется возможность просматривать протокол сообщений о событиях, происходящих в процессе выполнения приложения в режиме отладки. Протокол этих сообщений Вы можете просмотреть, выполнив команду Event Log пункта меню View. Щелкнув в появившемся окне правой кнопкой мыши, можно сохранить этот протокол в файле, прокомментировать его, очистить.

    Какие именно сообщения отображаются в этом окне, определяется настройкой отладчика. Можно влиять на содержимое этого окна с помощью функции OutputDebugString. Это функция API Windows, определенная следующим образом:

    OutputDebugString(lpOutputString: PChar);      ,
где lpOutputString - указатель на строку текста с нулевым значением.

    Например, если в текст программы вставить строку типа:

    OutputDebugString(PChar('Проверка работы функции OutputDebugString'));,
то окно Event Log содержит результат работы этой функции:


Рис.1. Окно Event Log

    Для встраивания отладочных средств в текст программы можно использовать процедуру Assert, которая объявлена следующим образом:

    Procedure Assert(Expr: Boolean; const Msg: String);   ,
где Expr - проверяемое условие, Msg - строка сообщения.

    Эту процедуру удобно применять для проверки истинности утверждений, которые должны быть истинны, но по каким-то причинам это не выполняется. Если проверяемое утверждение становится ложным, выполнение приложения прекращается, генерируется исключение 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.

Текст этого приложения можно взять здесь (оно сделано в Delphi 6).

    Результат работы приложения можно увидеть на рисунке 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++.




Предыдущий шаг Содержание Следующий шаг