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

Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на 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)















русский (ru)







Introduction

A stacktrace is sometimes called backtrace or call stack. This is a list of stack frames placed on the stack containing return address and local variables. A stacktrace is therefore useful to trace back the path of execution of your program (following the calls to procedures).

In order to obtain a stacktrace, the compiler first has to be directed to generate debug information using switches:

  • -g — generate debug information (in the default output format for the platform concerned, which is dwarf2 on a lot of platforms)
  • -gl — generate line numbers for debug information
  • -gs — generate older stabs debug information; don’t use both -gs and -gw
  • -gw — generate dwarf2 debug information; don’t use both -gs and -gw
  • -Xg — use external debug symbol file

SysUtils unit

SysUtils contains some routines useful for debugging exceptions.

{ Exception handling routines }
function ExceptObject: TObject;
function ExceptAddr: Pointer;
function ExceptFrameCount: Longint;
function ExceptFrames: PPointer;

System unit

The system unit contains some stack related routines:

function SysBackTraceStr(Addr:Pointer): ShortString; // Default address to string converter assigned to BackTraceStrFunc
procedure Dump_Stack(var f : text;bp:pointer); // Dump stack to text file
procedure DumpExceptionBackTrace(var f:text); // Dump backtrace to text file

Procedural variable BackTraceStrFunc responsible to translate memory address to string debug information. Default behavior is implemented by SysBackTraceStr.

Line information

If the line info debug output is selected (compiler switch -gl), the unit lineinfo is automatically included in the program. This unit makes sure that debuggers/exception handlers can find the line numbers of running code. It can be useful if you do not want to deploy a production executable with full debug info, but you do want useful information when errors occur.

Stabs

If the old stabs format (-gs) is used, the BackTraceStrFunc function is remapped to StabBackTraceStr.

DWARF

If the dwarf debugging format is selected (compiler switch -gw), the unit lnfodwrf is automatically included in the program and BackTraceStrFunc function is remapped to DwarfBacktraceStr.

Unit LCLProc

This Lazarus unit has some debug-related functions:

// Debugging
procedure RaiseGDBException(const Msg: string);
procedure RaiseAndCatchException;
procedure DumpExceptionBackTrace;
procedure DumpStack;
function GetStackTrace(UseCache: boolean): string;
procedure GetStackTracePointers(var AStack: TStackTracePointers);
function StackTraceAsString(const AStack: TStackTracePointers; UseCache: boolean): string;
function GetLineInfo(Addr: Pointer; UseCache: boolean): string;

Dump current call stack

See also FPC help on dumping stack/exception details:

  • DumpExceptionBackTrace
  • dump_stack
procedure DumpCallStack;
var
  I: Longint;
  prevbp: Pointer;
  CallerFrame,
  CallerAddress,
  bp: Pointer;
  Report: string;
const
  MaxDepth = 20;
begin
  Report := '';
  bp := get_frame;
  // This trick skip SendCallstack item
  // bp:= get_caller_frame(get_frame);
  try
    prevbp := bp - 1;
    I := 0;
    while bp > prevbp do begin
       CallerAddress := get_caller_addr(bp);
       CallerFrame := get_caller_frame(bp);
       if (CallerAddress = nil) then
         Break;
       Report := Report + BackTraceStrFunc(CallerAddress) + LineEnding;
       Inc(I);
       if (I >= MaxDepth) or (CallerFrame = nil) then
         Break;
       prevbp := bp;
       bp := CallerFrame;
     end;
   except
     { prevent endless dump if an exception occured }
   end;
  ShowMessage(Report);
end;

Dump exception call stack

The call stack of an exception can be obtained through SysUtils functions ExceptAddr, ExceptFrames and ExceptFrameCount.

uses SysUtils;

procedure DumpExceptionCallStack(E: Exception);
var
  I: Integer;
  Frames: PPointer;
  Report: string;
begin
  Report := 'Program exception! ' + LineEnding +
    'Stacktrace:' + LineEnding + LineEnding;
  if E <> nil then begin
    Report := Report + 'Exception class: ' + E.ClassName + LineEnding +
    'Message: ' + E.Message + LineEnding;
  end;
  Report := Report + BackTraceStrFunc(ExceptAddr);
  Frames := ExceptFrames;
  for I := 0 to ExceptFrameCount - 1 do
    Report := Report + LineEnding + BackTraceStrFunc(Frames[I]);
  ShowMessage(Report);
  Halt; // End of program execution
end;

Handling exceptions

Manual exception handling

Manual executions of exception handler can be inserted in many places in code.

try
  // ... some operation which should raise an exception...
  raise Exception.Create('Test error');
except
  on E: Exception do 
    DumpExceptionCallStack(E);
end;

System ExceptProc

If an unhandled exception occurs, the ExceptProc procedure variable is executed. Default behaviour is initialized by procedure InitExceptions in unit System. If you want to, this procedure can be reassigned to a custom handler.

An example:

procedure CatchUnhandledException(Obj: TObject; Addr: Pointer; FrameCount: Longint; Frames: PPointer);
var
  Message: string;
  i: LongInt;
  hstdout: ^Text;
begin
  hstdout := @stdout;
  Writeln(hstdout^, 'An unhandled exception occurred at $', sysBackTraceStr(addr), ' :');
  if Obj is exception then
   begin
     Message := Exception(Obj).ClassName + ' : ' + Exception(Obj).Message;
     Writeln(hstdout^, Message);
   end
  else
    Writeln(hstdout^, 'Exception object ', Obj.ClassName, ' is not of class Exception.');
  Writeln(hstdout^, BackTraceStrFunc(Addr));
  if (FrameCount > 0) then
    begin
      for i := 0 to FrameCount - 1 do
        Writeln(hstdout^, BackTraceStrFunc(Frames[i]));
    end;
  Writeln(hstdout^,'');
end;

TApplication.OnException

This event can be used to override default application wide exceptions handling. A custom logging mechanism could provide show custom dialog, log to file, console, sending report to mail, logging to HTTP server, e.g.

procedure TMainForm.CustomExceptionHandler(Sender: TObject; E: Exception);
begin
  DumpExceptionCallStack;
  Halt; // End of program execution
end;   

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Application.OnException := @CustomExceptionHandler;
end;

procedure TMainForm.ButtonClick(Sender: TObject);
begin
  raise Exception.Create('Test');
end;

Handling thread exceptions

Handling exceptions which are raised in threads has to be done manually. The main thread TThread method Execute is called from the function ThreadProc located in unit Classes.

function ThreadProc(ThreadObjPtr: Pointer): PtrInt;
begin
  ...
  try
    Thread.Execute;
  except
    Thread.FFatalException := TObject(AcquireExceptionObject);
  end; 
  ...
end;

In this function, the Execute method is enclosed in a try-except block and all exceptions are handled by assigning the exception object to the FatalException property of TThread object as last occurred exception object. So exceptions are not displayed to the user at all.

In every thread in the application, a separate try-except block should be inserted to catch all unhandled exceptions by a custom exception handler.

procedure TMyThread.Execute;
begin
  try
    // some erroneous code
  except
    on E: Exception do 
      CustomExceptionThreadHandler(Self, E);
  end;
end;

Then CustomExceptionThreadHandler can get the exception call stack and manage showing error messages or logging log reports to file. As the handler is executed from a thread, showing message dialog has to be done thread safe using the Synchronize method.

procedure TMainForm.CustomExceptionHandler(Thread: TThread; E: Exception);
begin
  Thread.Synchronize(DumpExceptionCallStack);
end;

Using map file

Use compiler switch -Xm to generate map file.

Exceptions in DLL

todo

See also

  • Profiling
  • Creating a Backtrace with GDB
  • MultiLog — A logging package
  • log4delphi — A logging package

External links

  • esprinter — tool to get stacktrace from running FreePascal program specified by process id and thread id (for Win32)
  • PascalBugReports — project intended to mimic EurekaLog/MadExcept but has not been worked on for a while

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

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

Если всё-таки Windows?

Если Вы планируете использовать Lazarus исключительно в среде Windows и, то, в принципе, никто вам не мешает подключить в uses модуль Windows и продолжать пользоваться уже привычными методами OutputDebugString, правда ваши сообщения будут попадать не в окно «Сообщения» к которому мы привыкли в Delphi, а в отдельное под названием «Журнал событий». Чтобы добраться до журнала событий, необходимо открыть в меню «Вид — Окна отладки — Журнал событий»

С пользовательским сообщением журнал событий выглядит вот так:

В принципе, ничего для тех, кто привык работать в Delphi, не поменяется за исключением расположения сообщений — в отдельном окне.

Аналог OutputDebugString в Lazarus «из коробки»

Для пользователей Lazarus в Linux всё не на много сложнее. Дело в том, что в Lazarus присутствует модуль dbugintf.pas, выводить различные отладочные сообщения, правда опять же, в отдельном окне. Чтобы эта возможность заработала, необходимо выполнить следующие действия:

1.Собрать утилиту  debugserver, которая находится в папке с Lazarus по пути: %Lazarus%toolsdebugserver

По сути, эта утилита сильно напоминает «Журнал событий», о котором шла речь выше. Вот как выглядит пустой debugserver:

2. Добавить debugserver в список внешних средств Lazarus. Для этого заходим в меню: Сервис — Настроить внешние средства:

добавить утилиту в список следующим образом:

Теперь debugserver появится в меню Lazarus:

3. Подключить в uses любого модуля вашего проекта модуль dbugintf и включить вывод сообщений в окно debugserver, используя следующий метод:

procedure SetDebuggingEnabled(const AValue : boolean);

Думаю, тут всё понятно и без комментариев — передача в метод значение True включается вывод сообщений, False — отключает. Для вывода различных сообщений в debugserver можно воспользоваться следующими методами:

procedure SendBoolean(const Identifier: string; const Value: Boolean);
procedure SendDateTime(const Identifier: string; const Value: TDateTime);
procedure SendInteger(const Identifier: string; const Value: Integer; HexNotation: Boolean = False);
procedure SendPointer(const Identifier: string; const Value: Pointer);
procedure SendDebugEx(const Msg: string; MType: TDebugLevel);
procedure SendDebug(const Msg: string);
procedure SendMethodEnter(const MethodName: string);
procedure SendMethodExit(const MethodName: string);
procedure SendSeparator;
procedure SendDebugFmt(const Msg: string; const Args: array of const);
procedure SendDebugFmtEx(const Msg: string; const Args: array of const; MType: TDebugLevel);

Чтобы продемонстрировать работу методов, напишем следующий тестовый код на Lazarus:

procedure TForm1.Button2Click(Sender: TObject);
var b: boolean;
    i: integer;
    d: TDateTime;
begin
  SetDebuggingEnabled(True);
  SendMethodEnter('Button2Click Enter');
  b:=True;
  SendBoolean('b',b);
  i:=100;
  SendInteger('i',i,False);
  SendInteger('i as hex',i,True);
  d:=Now;
  SendDateTime('d',d);
  SendSeparator;
  SendDebugEx('Это сообщение будет выглядеть в окне debugserver как ошибка', dlError);
  SendMethodExit('Button2Click Enter');
end;

Здесь мы воспользовались различными методами модуля dbugintf и отправили в debugserver несколько сообщений, которые будут выглядеть следующим образом:

Соответственно, все сообщения читаются снизу вверх и при необходимости их можно сохранить в буфер обмена или отдельный файл.

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

На сегодня всё. Продолжаем разбираться с Lazarus и попутно в нем же работать :)

5
3
голоса

Рейтинг статьи

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Everytime I use a raise Exception.create('...');, it shows, differently from Delphi, the following box:

[my message]

Press OK to ignore and risk data corruption.
Press Cancel to kill the program.

I just want to change this default message and keep only my part.

Does someone know how can I do it?

asked Jun 4, 2013 at 0:44

felipe.zkn's user avatar

felipe.zknfelipe.zkn

2,0047 gold badges31 silver badges63 bronze badges

8

To configure my own exception message, I did the following:

In the private declarations of application’s main form:

procedure onExcept(sender: TObject; e: Exception);

In the OnCreate event of the main form:

procedure TfrmMain.formCreate(sender: TObject);
begin
    application.onException := @onExcept;
end;

procedure TfrmMain.onExcept(sender: TObject; e: Exception);
begin
    //...
end;

It’s important to note that the @ operator is required if you’re using Lazarus. If I didn’t put it, the compiler would consider onExcept as a function call. Delphi adds it internally, so you don’t have to worry about it.

If you want to change this behavior, use {$mode Delphi} instead of {$mode ObjFPC} directive.

answered Jun 5, 2013 at 13:04

felipe.zkn's user avatar

felipe.zknfelipe.zkn

2,0047 gold badges31 silver badges63 bronze badges

272 / 176 / 30

Регистрация: 16.03.2017

Сообщений: 1,626

1

Отладочные сообщения

31.07.2017, 13:59. Показов 3139. Ответов 7


Студворк — интернет-сервис помощи студентам

Добрый день, подскажите плиииз.

В Лазарус (IDE) подобное вообще предусмотрено?

Что-то вроде вывода консольных сообщений (в идеале цветных). Поработал немного в java под андроид и под спринг — там это в основу IDE встроено!

Не по теме:

Жутко раздражает когда не могу вывести строку с ошибкой прежде чем программа окончательно (по непонятной причине) зависнет. (приходится пошагово команды отключать пока не доберусь до команды с ошибкой) Текстовый лог писать тоже не лучшее решение…



0



Супер-модератор

Эксперт Pascal/DelphiАвтор FAQ

32582 / 21053 / 8131

Регистрация: 22.10.2011

Сообщений: 36,326

Записей в блоге: 8

31.07.2017, 15:03

2

Я в подобном случае ставлю несколько брекпойнтов в критических местах программы, но снимаю галку «Останов», и добавляю каждому бряку свое сообщение:

Отладочные сообщения

А в настройках журнала событий (Ctrl+Alt+V, правый клик — «Параметры журнала событий») включаю «Сообщения -> Точка останова». И запускаю программу. В результате вижу, где что сработало, а до чего не дошло:

Отладочные сообщения



1



272 / 176 / 30

Регистрация: 16.03.2017

Сообщений: 1,626

31.07.2017, 15:11

 [ТС]

3

Цитата
Сообщение от volvo
Посмотреть сообщение

Я в подобном случае ставлю несколько брекпойнтов в критических местах программы

То есть стандартной консольной системы нет? Типа console.log(«hi») в JavaScript?

Добавлено через 2 минуты
В java-spring встречал класс который аналогично Вашим брейпоинтам выводил строки в консоль (6 цветов) которые в релизе можно было «переключить» мини-настройкой (кодом) в запись в текстовые логи. В javascript есть возможность выводить цветные сообщения в отладочную консоль. В андроиде тоже есть свой логкэт… Почти в каждом языке подобное есть…



0



D1973

31.07.2017, 16:00

Не по теме:

Цитата
Сообщение от andyj
Посмотреть сообщение

Почти в каждом языке подобное есть

Хм-м… Причем тут язык, если дело касается настроек среды?



0



Супер-модератор

Эксперт Pascal/DelphiАвтор FAQ

32582 / 21053 / 8131

Регистрация: 22.10.2011

Сообщений: 36,326

Записей в блоге: 8

31.07.2017, 16:10

5

andyj, есть LazLogger, который пишет либо в консоль (если она открыта), либо в файл.



1



272 / 176 / 30

Регистрация: 16.03.2017

Сообщений: 1,626

31.07.2017, 17:26

 [ТС]

6

Цитата
Сообщение от volvo
Посмотреть сообщение

есть LazLogger, который пишет либо в консоль (если она открыта), либо в файл.

Нашел (по Вашим ссылкам) http://wiki.freepascal.org/DebugServer
лежит в lazarustoolsdebugserverdebugserver.lpr
(нужно скомпилировать)
инструкция по использованию lazarustoolsdebugserverREADME.txt
(очень простая)

Работает вроде не плохо, хотя и кучи (крайне необходимых/привычных мне) функций не хватает…

Хочу доработать для себя! Следующий вопрос: Вы сами подобным пользуетесь? или хотите? (делать ее только для себя или поиграться с опенсорсностью — сложнее, и дольше)

Не по теме:

…привык в java/android/delphi/и в особенности С++ натыкаться на ответ «не майся дурью — существующих инструментов вполне хватает для любой программы»
(лично для меня это звучит почти как «зачем тебе ООП — асемблерных команд набираемых в консоли вполне достаточно»)



0



Супер-модератор

Эксперт Pascal/DelphiАвтор FAQ

32582 / 21053 / 8131

Регистрация: 22.10.2011

Сообщений: 36,326

Записей в блоге: 8

31.07.2017, 17:35

7

Цитата
Сообщение от andyj
Посмотреть сообщение

Вы сами подобным пользуетесь? или хотите?

Нет, не пользуюсь. Ни LazLogger-ом, ни DebugServer-ом. То, чем пользуюсь (иногда, очень редко) я описал выше. В основном мне хватает пошагового прохода. В самом крайнем случае — пишу лог в файл. Так что не майся дурью… (далее — по тексту выше)

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



1



andyj

31.07.2017, 17:57

 [ТС]


    Отладочные сообщения

Не по теме:

Цитата
Сообщение от volvo
Посмотреть сообщение

Нет, не пользуюсь. Ни LazLogger-ом, ни DebugServer-ом. То, чем пользуюсь (иногда, очень редко) я описал выше. В основном мне хватает пошагового прохода. В самом крайнем случае — пишу лог в файл. Так что не майся дурью… (далее — по тексту выше)

Либо что-то не так со мной, либо с моими методиками разработки, либо со сложностью написанных мной программ…

2 дня (почти все выходные) убил на поиск ошибки методом «перебора неправильных веток». Написал простую ОРМ которая динамически создает десяток таблиц/справочников, заполняет их дефолтными значениями, абгрейдит столбцы при изменении версии и выводит результат в полностью графический компонент написанный с нуля. Ошибка при старте… Ругалось в графике на запросе к справочнику — в конце оказалось что не корректно обрабатывает дубль названия справочника… 2 дня!!! тысячи перезапусков и поиска логических нестыковок…. Вместо одной отлаженной команды «вывели аррей в лог» (в старых Делфи я для себя подобное писал) и 5ти минут просмотра 3х страничного лога… причем в цветах и с отступами…

…или хитровыкрученные базы данных где одна команда добавляет десяток перекрученных строк и может не стыковаться с предыдущей командой… запускал миллионы (2 ночи выходных) тестов чтобы поймать нестыковки в бесконечных логах…

…или в android надо делать сложные запросы в sqlite, хранить в ссылках и выводить частями… глюк на экране никак не объяснит кто виноват — проще всего всю ссылку на запрос/таблицу отправить в специальную функцию (написанный мной) которая отобразит ее в моем-же окошечном-логере — 10 секунд просмотра таблицы «по диагонали» и ошибка найдена…

а сколько раз надо было вести замеры времени «начато в» «закончено в», «думало целых 4.5 секунды = самая медленная операция обращение к запросу №…» — как без этого оптимизацию кода проводить?

…ладно С++шники… они «консерваторы»… Но в java подобным во всю пользуются! (я работал с такой командой — они писали софт на США совместно с другими странами)



0



Понравилась статья? Поделить с друзьями:
  • Lazarus ubuntu ошибка
  • Lazarus try except текст ошибки
  • Layout ошибка чтения файла
  • Laravel логирование ошибок
  • Laravel логи ошибок