Отладка приложений в Lazarus — Lazarus. Студия разработки

Отладка приложений в Lazarus

  • |
  • Post By :
  • |
  • Опубликовано : 10 декабря 2024

Отладка — важнейший этап разработки программного обеспечения. В процессе создания приложений на языках программирования, особенно на Pascal с использованием среды Lazarus, разработчикам необходимо уметь находить и устранять ошибки. Lazarus предоставляет мощные инструменты для отладки, которые облегчают эту задачу. В этой статье я покажу на примерах основные аспекты отладки приложений в Lazarus. Также рассмотрим советы для повышения эффективности этого процесса.

Основные инструменты отладки Lazarus

В Lazarus есть несколько инструментов, которые помогают в процессе отладки:

  • Встроенный отладчик, который позволяет устанавливать точки останова, просматривать значения переменных и контролировать выполнение программы.
  • Вывод информации: Возможность использования метода writeln, ShowMessage или ведения журналов для отслеживания состояния программы.
  • Просмотр переменных: Отладчик позволяет видеть значение переменных во время выполнения, что помогает находить ошибки и их причины.

Подготовка тестового приложения

Давайте подготовим приложение, на котором мы сможем посмотреть, как работает отладчик. Пусть это приложение калькулятор. Конечно, это будет не полноценный калькулятор с вводом любых выражений. Наша цель скорее посмотреть на возможности отладки, поэтому мы добавим на форму два текстовых поля ввода, разместим 4 кнопки: плюс, минус, умножить, разделить, — и добавим метку для вывода результата(рисунок 1).

Рисунок 1. Форма и компоненты тестового приложения

Перед тем, как начать писать код непосредственно для кнопок-действий, давайте добавим 3 вспомогательных метода (две функции и процедуру), для работы с компонентами формы. Объявим их в секции private нашего класса формы. Полный листинг модуля с добавленными функциями и процедурой приведен ниже.

unit umain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, uPSComponent;

type

  { TForm1 }

  TForm1 = class(TForm)
    btPlus: TButton;
    btMinus: TButton;
    btMult: TButton;
    btDiv: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    lbResult: TLabel;
  private
      function arg1: Double;
      function arg2: Double;
      procedure OutActionResult(sAction:string;resultValue:Double);
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }
function TForm1.arg1: Double;
begin
  result:=StrToFloat(Edit1.Text);
end;

function TForm1.arg2: Double;
begin
  result:=StrToFloat(Edit2.Text);
end;

procedure TForm1.OutActionResult(sAction: string; resultValue: Double);
begin
  lbResult.Caption := Edit1.Text+' '+sAction+' '+Edit2.Text+' = '+FloatToStr(resultValue);
end;

end.

Функция arg1 будет возвращать нам значение из текстового поля Edit1, аналогично arg2 будет возвращать значение из Edit2. Процедура OutActionResult будет выводить результат в метку lbResult. Таким образом, при написании кода кнопок нам уже не нужно будет обращаться к компонентам формы напрямую. Мы будем использовать подготовленные для этого методы.

Теперь добавим код для каждой из кнопок. Каждая кнопка должна выполнять действия над числами, которые пользователь введет в Edit1 и Edit2. Добавление обработчика для конкретной кнопки происходит при двойном клике по этой кнопке.

procedure TForm1.btPlusClick(Sender: TObject);
begin
  OutActionResult('+',arg1+arg2);
end;

procedure TForm1.btMinusClick(Sender: TObject);
begin
  OutActionResult('-',arg1-arg2);
end;

procedure TForm1.btMultClick(Sender: TObject);
begin
  OutActionResult('x',arg1*arg2);
end;
procedure TForm1.btDivClick(Sender: TObject);
begin
  OutActionResult(':',arg1/arg2);
end; 

Как видите, благодаря зараннее подготовленным функциям, код методов выглядит достаточно лаконично. Запустим приложение, введем числовые значения в текстовые поля и убедимся, что программа работает (Рисунок 2).

Рисунок 2. Тест работы программы

Приступаем к отладке

Теперь давайте попробуем в одно из полей ввода вписать не число, а строку. При попытке выполнить какое-либо действие (например +), мы сразу получим ошибку, которая показана на рисунке 3.

Рисунок 3.

Как определить, в каком месте в нашем коде эта ошибка происходит? Давайте закроем режим выполнения проекта и вернемся в режим разработки. Ошибка у нас возникла, когда мы нажали на кнопку «+» (на самом деле она возникнет при нажатии на любое из действий, если мы ввели не число). Откроем обработчик кнопки «+» и поставим там точку останова: для этого нужно кликнуть мышью по левой (серой) части редактора кода, расположенной за вертикальной шкалой нумерации строк (см. рисунок 4). При этом на месте клика должна появиться красная точка, а строка, на которую установлена точка останова подсвечивается красным.

Рисунок 4. Установка точки останова

После установки точки останова снова запустим наше приложение, введем вместо первого числа какую-то строку и нажмем кнопку «+». Теперь наше приложение остановит выполнение на точке останова, которую мы установили, а мы сможем продолжить это выполнение пошагово в отладчике (Рисунок 5).

Рисунок 5. Выполнение программы приостановлено на точке останова.

Находясь на этапе, который показан на рисунке 5, нажмите на кнопку F7 (на клавиатуре). Мы «проваливаемся» сначала в функцию arg1. Находясь в функции arg1, нажмите кнопку F8 несколько раз, пока не появится ошибка. Ошибка возникает на строке «result:=StrToFloat(Edit1.Text);» (в моем коде на рисунке 5, это 45-я строка). Теперь мы точно знаем, где ошибка и понимаем, что функция StrToFloat не может правильно преобразовать передаваемое в нее значение. Для того чтобы поймать и обработать исключение, в синтксисе FreePascal существует конструкция «try … except». Ниже приведен измененный код функции arg1.

function TForm1.arg1: Double;
begin
  try
    result:=StrToFloat(Edit1.Text);
  except
    result:=0;
  end;
end; 

Теперь функция arg1 возвращает число из Edit1, но если введенные данные не удается преобразовать в число, то arg1 вернет 0 и дальнейший расчет корректно отработает, ошибка не возникнет. Не трудно догадаться, что такой же перехват ошибки нужно добавить и в функцию arg2. Результат работы программы с обработанной ошибкой показан на рисунке 6.

Рисунок 6. Нажата кнопка «-«

Полезные горячие клавиши для отладки

  • F7 — шаг со входом в процедуру/функцию
  • F8 — шаг в обход (будет выполнена строка полностью, на которой стоит курсор выполнения
  • Shift+F8 — шаг с выходом из процедуры/функции

В этой статье мы немного познакомились с процессом отладки. Обычно на практике всё гораздо проще. Главное начать. Кстати, в рассмотренной нами программе осталась еще по крайней мере одна необработанная ситуация. Попробуйте найти ее и описать в комментариях к этой статье, а также обработать ее самостоятельно. Ниже привожу итоговый листинг главного модуля программы.

unit umain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, uPSComponent;

type

  { TForm1 }

  TForm1 = class(TForm)
    btPlus: TButton;
    btMinus: TButton;
    btMult: TButton;
    btDiv: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    lbResult: TLabel;
    procedure btDivClick(Sender: TObject);
    procedure btMinusClick(Sender: TObject);
    procedure btMultClick(Sender: TObject);
    procedure btPlusClick(Sender: TObject);
  private
      function arg1: Double;
      function arg2: Double;
      procedure OutActionResult(sAction:string;resultValue:Double);
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }
function TForm1.arg1: Double;
begin
  try
    result:=StrToFloat(Edit1.Text);
  except
    result:=0;
  end;
end;

function TForm1.arg2: Double;
begin
  try
    result:=StrToFloat(Edit2.Text);
  except
    result:=0;
  end;
end;

procedure TForm1.OutActionResult(sAction: string; resultValue: Double);
begin
  lbResult.Caption := Edit1.Text+' '+sAction+' '+Edit2.Text+' = '+FloatToStr(resultValue);
end;

procedure TForm1.btPlusClick(Sender: TObject);
begin
  OutActionResult('+',arg1+arg2);
end;

procedure TForm1.btMinusClick(Sender: TObject);
begin
  OutActionResult('-',arg1-arg2);
end;

procedure TForm1.btMultClick(Sender: TObject);
begin
  OutActionResult('x',arg1*arg2);
end;
procedure TForm1.btDivClick(Sender: TObject);
begin
  OutActionResult(':',arg1/arg2);
end;


end.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

*