Как найти ошибку в лазарусе

Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

121

{Если значение переменной m выходит за пределы области допустимых значений, то выдается сообщение об ошибке.}

else

writeln(‘ОШИБКА ПРИ ВВОДЕ!!!’);

end

end.

Понятно, что чем меньше в программе ошибок, тем она лучше. В очень хорошей программе ошибок нет вообще. А это значит, что программист должен не только основательно продумать алгоритм, поставленной задачи, но и предугадать ошибки, которые может допустить пользователь, работая с программой.

Если пользователь допустил ошибку, например, при вводе данных, его необходимо проинформировать об этом. Для этого можно воспользоваться функцией MessageDlg, которая выводит сообще-

ние в отдельном окне. В общем виде функцию записывают так:

MessageDlg(сообщение, тип_сообщения, [список_кнопок], справка);

где

сообщение – текст, который будет отображен в окне сообщения;

тип_ сообщения – определяет внешний вид окна (табл. 3.2);

список_кнопок – константы (перечисляются через запятую), определяющие тип кнопок окна сообщения (табл. 3.3);

справка – номер окна справочной системы, которое будет вы-

ведено на экран, если нажать F1, параметр равен нулю, если использование справки не предусмотрено.

Таблица. 3.2. Тип окна сообщения.

Параметр

Тип окна сообщения

mtInformation

информационное

mtWarning

предупредительное

mtError

сообщение об ошибке

mtConfirmation

запрос на подтверждение

mtCustom

обычное

Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

122

Таблица. 3.3. Тип кнопки в окне сообщения.

Константа

Кнопка в окне сообщения

mbYes

Да

mbNo

Нет

mbOk

Ок

mbCancel

Отмена

mbAbort

Прервать

mbRetry

Повторить

mbIgnore

Пропустить

mbHelp

Помощь

Вернемся к задаче решения квадратного уравнения (задача 3.3). Нами был рассмотрен алгоритм решения этой задачи и написана программа на языке программирования Free Pascal. Реализуем эту задачу в среде Lazarus. Создадим новый проект41 (рис. 3.20).

Для организации ввода коэффициентов уравнения внедрим на форму четыре объекта типа надпись (Label1, Label2,

Label3, Label4) и три поля ввода (Edit1, Edit2, Edit3).

Корни уравнения или сообщение Рисунок 3.20: Форма для ре- об их отсутствии будем выводить

шения квадратного уравнения в надпись Label542.

Все действия по вычислению корней квадратного уравнения будут выполняться при нажатии кнопки Button1.

При вводе данных в программе могут возникнуть следующие ошибки:

•в поле ввода оказалась строка, которую невозможно преобразовать в число;

•значение коэффициента a равно нулю43.

Для того чтобы не допустить подобных ошибок необходимо контролировать данные, вводимые пользователем. Применим для этой цели встроенную процедуру Val(S,X,Kod), которая преоб-

разовывает строку S в целое или вещественное число X. Если преоб-

41 Подробно о создании проекта см. в первой главе.

42 На этапе конструирования формы Label5.Visible:=false.

43 В этом случае при вычислении корней произойдет деление на ноль.

Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

123

разование прошло успешно, то параметр Kod принимает значение,

равное нулю, а результат преобразования записывается в переменную X. В противном случае Kod содержит номер позиции в строке S, где

произошла ошибка, и содержимое переменной X не меняется. Далее

приведен фрагмент программы с подробными комментариями: procedure TForm1.Button1Click(Sender: TObject);

var

a,b,c,d,x1,x2: real; kod1,kod2,kod3:integer; begin

//Ввод значений коэффициентов уравнения. //Из поля ввода Edit1 считывается строка //символов и преобразовывается в вещественное //число, если преобразование прошло успешно, //то kod1=0 и полученное число записывается //в переменную a.

val(Edit1.Text,a,kod1);

val(Edit2.Text,b,kod2);

val(Edit3.Text,c,kod3);

//Если преобразования прошли успешно, то if (kod1=0) and (kod2=0) and (kod3=0) then

//проверить чему равен первый коэффициент. //Если значение первого коэффициента //равно нулю, то

if a=0 then

//выдать соответствующее сообщение. MessageDlg(‘Введите не нулевое значение а’, mtInformation,[mbOk],0)

else

//иначе перейти к решению уравнения begin

d:=b*b-4*a*c; Label5.Visible:=true; if d<0 then

Label5.Caption:=’В уравнении’+ chr(13)+’нет действительных корней’

else begin

Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

124

x1:=(-b+sqrt(d))/2/a; x2:=(-b-sqrt(d))/(2*a);

Label5.Caption:=’X1=’+

FloatToStr(x1)+chr(13)+

‘X2=’+FloatToStr(x2);

end;

end else

//Преобразование не выполнено, //выдать сообщение.

MessageDlg(‘Введите числовое значение’, mtInformation,[mbOk],0);

end;

Результаты работы программы показаны на рис. 3.21 — 3.24.

Рисунок 3.22: Обработка

ошибки ввода данных — в поле

Рисунок 3.21: Обработка

ввода строка, которую невоз-

ошибки ввода данных — коэффи-

можно преобразовать в число

циент a равен 0

(коэффициент равен символу B)

Рисунок 3.23: Решение квад-

ратного уравнения 3x2+4x+5=0

Рисунок 3.24: Вычисление

(корней нет)

корней квадратного уравнения








English (en)



suomi (fi)





















Free Pascal supports exceptions. Exceptions are useful for error handling and avoiding resource leaks. However, bear in mind that exceptions have a performance impact.

The official documentation is here: Reference guide chapter 17.

By default exceptions are disabled. You can opt in by using the ObjFPC or DELPHI Compiler Mode, or adding -Sx to the compiler commandline. This enables the try, raise, except, and finally reserved words for use in your own code, but it doesn’t enable exception generation from the RTL. To enable the RTL to raise exceptions instead of generating runtime errors, use the SysUtils unit in your program.

The base Exception class is found in the SysUtils unit. All exceptions should preferably use this class or its descendants.

SysUtils automatically sets up a basic exception catcher, so any otherwise uncaught exception is displayed in human-readable form, as the program terminates. To generate readable callstacks from caught exceptions in your own code, without necessarily terminating the program, you can use SysUtils functions ExceptAddr, ExceptFrames, ExceptFrameCount, and BackTraceStrFunc.

Examples

Note that Pascal uses different keywords than some other languages: raise instead of throw, and except instead of catch. Also, as a compiler design choice, each try-block can pair with either an except or finally block, but not both at the same time. You’ll need to nest try-blocks if you need except and finally protecting the same code.

Error handling

uses sysutils;

begin
  try
    // Do something that might go wrong.
  except
    begin
      // Try to recover or show the user an error message.
    end;
  end;
end.

Cleaning up resources

try
  // Do something that might go wrong.
finally
  // Clean-up code that is always called even if an exception was raised.
end;

Exception leaking

Finally-blocks don’t destroy exception objects. Any exception that reaches the program’s «end.» will trigger a memory leak warning. An extra except block can be used to consume such exceptions. This is Delphi-compatible.

begin
  try
    // Your main program, where an exception object is created.
  finally
    try
      // Clean-up code.
    except
    end;
  end;
end.

Signalling problems

raise Exception.Create('Helpful description of what went wrong');

Using specialised exception types to signal different problems

type EMyLittleException = Class(Exception);

begin
  try
    raise EMyLittleException.Create('Foo');
  except
    on E : EMyLittleException do writeln(E.Message);
    on E : Exception do writeln('This is not my exception!');
    else writeln('This is not an Exception-descendant at all!');
  end;
end;

Re-raising exceptions

try
  // Do something that might go wrong.
except
  // Try to recover or show the user an error message.
  if recoveredSuccessfully = FALSE then
    raise;
end;

Exception classes

SysUtils defines and raises many specific exception classes.

With SysUtils included in your program, and exceptions enabled, various runtime errors are changed into exceptions. Processor-level interrupts like SIGSEGV or SIGFPU, which normally translate to run-time errors, are also changed to exceptions. For example, run-time error 200 (division by zero) becomes EDivByZero or EZeroDivide, while run-time error 216 (a general protection fault) becomes EAccessViolation.

Best practice

  • Raise exceptions to signal that an operation could not be completed, where it normally should have succeeded.
  • Do not use exceptions as part of expected control flow. Instead, add checks for common error conditions and return error values the old-fashioned way. For example, input parsing problems or file existence fails are usually not truly exceptional.
  • But do raise an exception if it’s critical that the error is noticed; programmers may forget to check for returned error values.
  • Naming convention: Prefix exception class names with a capital E.
  • Re-raise exceptions in except-blocks using raise; if you were unable to recover from the problem; this preserves the original exception’s callstack.
  • Be careful about using the catch-all base Exception class, since the underlying code or OS/filesystem might produce an unanticipated exception that slips through your exception handler, potentially corrupting the program state.
  • When writing a unit or library, if exceptions are used at all, they should be documented clearly up front. This way the unit user knows what to expect.
  • Keep exception handling away from code that needs to run as fast as possible.

Performance

Compiler optimisation levels don’t make much difference. All exception blocks use a small amount of wrapper code that can’t be optimised away. There are different ways for a compiler to produce exception code, with varying performance implications. As of FPC 3.0.4, the default exception mechanism uses the standard setjmp/longjmp style. FPC also supports OS-provided Structured Exception Handling; this is the default on Win64, and can be enabled on Win32 (recompile the compiler with $define TEST_WIN32_SEH). Other mechanisms may be added to FPC in the future.

To get a better feel for what’s going on, try writing a small test program and compiling it with the -a switch. This leaves behind a human-readable assembly file.

Notes on the setjmp/longjmp method:

  • Try-statements insert some extra address calculations, a stack push and pop, some direct jumps, and a conditional jump. This is the setup cost of an exception frame, even if no exception is raised.
  • Except-statements insert the above, plus a push and pop, more direct jumps, and another conditional jump.
  • Finally-statements add a pop and a conditional jump.
  • Raise-statements create a string and pass control to FPC’s exception raiser. The string creation itself can spawn an implicit exception frame for the function/method, due to dynamic string allocations, even if the raise is not executed. This is why in e.g. container types one often sees the raise moved to a separate local (private) procedure. This localises the exception frame to that procedure, so the performance hit is only taken if the procedure is called.

Furthermore, generating a human-readable callstack from a raised exception involves time-consuming stack traversal and string manipulation.

With all that said, outside of heavy processing code, the convenience of exceptions usually outweighs their performance impact. Don’t feel bad about using them if it makes your code better.

Further reading

Logging exceptions

Avoiding implicit try finally section

Exceptions vs Error codes — a situation where exceptions might be a danger in some code (see middle of this page)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Grids,
  StdCtrls, Spin;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Save_B: TButton;
    Load_B: TButton;
    P_E: TEdit;
    I_L: TLabel;
    Z_L: TLabel;
    R_L: TLabel;
    P_L: TLabel;
    Count_SE: TSpinEdit;
    I_SG: TStringGrid;
    Z_SG: TStringGrid;
    R_SG: TStringGrid;
    procedure Count_SEChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Load_BClick(Sender: TObject);
    procedure Save_BClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
type
   TPeople = record
     Name, Family : ShortString;
     Rost, Ves : Double;
   end;
{$R *.lfm}
 
 
{ TForm1 }
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  I_SG.RowCount:=Count_SE.Value+1;
  I_SG.Cells[0,0]:='Фамилия';
  I_SG.Cells[1,0]:='Имя';
  I_SG.Cells[2,0]:='Рост';
  I_SG.Cells[3,0]:='Вес';
  Z_SG.Cells[0,0]:='Фамилия';
  Z_SG.Cells[1,0]:='Имя';
  Z_SG.Cells[2,0]:='Рост';
  Z_SG.Cells[3,0]:='Вес';
  R_SG.Cells[0,0]:='Фамилия';
  R_SG.Cells[1,0]:='Имя';
  R_SG.Cells[2,0]:='Рост';
  R_SG.Cells[3,0]:='Вес';
end;
 
 
 
procedure TForm1.Save_BClick(Sender: TObject);
var
  people : TPeople;
  f: File;
  i: Integer;
begin
  AssignFile(f,'data.dat');
  Rewrite(f,1);
  for i:=1 to I_SG.RowCount-1 do
  begin
    people.Family:=I_SG.Cells[0,i];
    people.Name:=I_SG.Cells[1,i];
    people.Rost:= StrToFloat(I_SG.Cells[2,i]);
    people.Ves:= StrToFloat(I_SG.Cells[3,i]);
    BlockWrite(f,people.Name,SizeOf(people.Name));
    BlockWrite(f,people.Family,SizeOf(people.Family));
    BlockWrite(f,people.Rost,SizeOf(people.Rost));
    BlockWrite(f,people.Ves,SizeOf(people.Ves));
  end;
  CloseFile(f);
end;
 
procedure TForm1.Load_BClick(Sender: TObject);
var
  people : Array[1..100] of TPeople;
  f : file;
  i, count, j : Integer;
  b : String;
begin
  AssignFile(f,'data.dat');
  Reset(f,1);
  count := 0;
  while not EOF(f) do
begin
  inc(count);
  BlockRead(f,people[count].Name,SizeOf(people[count].Name));
  BlockRead(f,people[count].Family,SizeOf(people[count].Family));
  BlockRead(f,people[count].Rost,SizeOf(people[count].Rost));
  BlockRead(f,people[count].Ves,SizeOf(people[count].Ves));
  end;
  CloseFile(f);
  Z_SG.RowCount:=count+1;
  for i := 1 to count do
  begin
    Z_SG.Cells[1,i]:=people[i].Name;
    Z_SG.Cells[0,i]:=people[i].Family;
    Z_SG.cells[2,i]:=FloatToStr(people[i].Rost);
    Z_SG.cells[3,i]:=FloatToStr(people[i].Ves);
    j:=0;
   b:=P_E.Text;
   if (pos(b,people[i].Name)=1)  then
   if (people[i].Ves = people[i].Rost - 100) then
   begin
     inc(j);
     R_SG.RowCount:=j+1;
     R_SG.Cells[1,i]:=people[i].Name;
     R_SG.Cells[0,i]:=people[i].Family;
     R_SG.Cells[2,i]:=FloatToStr(people[i].Rost);
     R_SG.Cells[3,i]:=FloatToStr(people[i].Ves);
   end;
   end;
   if j = 0 then
   begin
   R_SG.RowCount:=2;
   R_SG.Cells[1,i]:='Заданным';
   R_SG.Cells[0,i]:='Человека по';
   R_SG.Cells[2,i]:='Параметрам';
   R_SG.Cells[3,i]:='Не найдено';
   end;
 
end;
 
procedure TForm1.Count_SEChange(Sender: TObject);
begin
  I_SG.RowCount:=Count_SE.Value+1;
end;
 
end.

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

Ошибка компиляции

Одной из основных ошибок при работе с Lazarus является ошибка компиляции. Это означает, что компилятор не может преобразовать исходный код в исполняемый файл из-за ошибок в коде.

Существует несколько причин, по которым может возникнуть ошибка компиляции:

  • Синтаксическая ошибка в исходном коде
  • Отсутствие необходимых компонентов или библиотек
  • Некорректные параметры проекта

Чтобы исправить ошибку компиляции, необходимо:

  1. Проверить синтаксис исходного кода на наличие ошибок
  2. Проверить настройки проекта и убедиться, что все необходимые компоненты и библиотеки установлены
  3. Убедиться, что параметры проекта заданы правильно
  4. Попробовать перекомпилировать проект

Ошибка запуска

Если Lazarus успешно скомпилирован, но не запускается, то в этом случае возникает ошибка запуска. Ошибка запуска может быть вызвана множеством факторов, включая неправильные настройки окружения, несовместимые версии библиотек и компонентов, а также проблемы с операционной системой.

Для исправления ошибки запуска, рекомендуется:

  1. Проверить настройки окружения и установить необходимые пакеты и библиотеки
  2. Убедиться, что используемые версии библиотек и компонентов совместимы
  3. Попробовать запустить Lazarus с правами администратора
  4. Проверить журналы системы на наличие ошибок, которые могут быть связаны с запуском Lazarus

Ошибка открытия проекта

Если Lazarus не может открыть проект, то возникает ошибка открытия проекта. Это может быть вызвано неправильными настройками, поврежденным проектом или проблемами с файловой системой.

Для исправления ошибки открытия проекта, рекомендуется:

  1. Проверить настройки путей к файлам и убедиться, что они корректны
  2. Проверить файлы проекта на наличие повреждений
  3. Попробовать скопировать проект в другую папку и открыть его там

Ошибка совместимости

Если Lazarus не может открыть или скомпилировать проект, то может быть проблема совместимости. Это может быть вызвано различными факторами, включая несовместимые версии библиотек, компонентов или ОС.

Для исправления ошибки совместимости, рекомендуется:

  1. Проверить требования к версии Lazarus и установить соответствующую версию
  2. Установить все необходимые пакеты и библиотеки, которые требуются для компиляции проекта
  3. Проверить настройки проекта и убедиться, что они совместимы с Lazarus

Заключение

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

Зато, если выкинет в середине цикла, который должен обработать все элементы (и после него ещё должна быть обработка), программа вообще никак не будет работать. Зависнет, например. А так, элемент будет пропущен и обработка продолжится. К тому же, если исключения выбрасываются библиотекой, что мне искать все классы исключений, которые она может выбросить? Но я не спорю — это действительно неправильно. Вопрос в том как с ними работать по-человечески? Или, exceptions — это, из серии «гладко было на бумаге, да забыли про овраги»?

Добавлено спустя 1 минуту 53 секунды:
2MageSlayer:
Такое же, как и всё остальное. Один из случаев, когда я не понимаю, как с ними правильно работать.
Ещё, например, меня интересует тонна проверок на nil. Ведь, по-идее, в коде не должно быть таких проверок?

Понравилась статья? Поделить с друзьями:
  • Как найти ошибку в контакте
  • Как найти ошибку в компьютере синего экрана
  • Как найти ошибку в компьютере и исправить ее
  • Как найти ошибку в компьютере виндовс 7
  • Как найти ошибку в компьютере error