Forum > Debugger
How to Debug and Step into Assert() Function in Lazarus?
Aruna:
Hi everyone,
I'm working on a simple Lazarus project, and I'm using Assert() statements to catch unexpected conditions in my code. However, when an assertion fails, the program terminates, and I'm unable to step into the Assert() function to examine the context around the failure directly. I want to understand better what’s causing the assertion to trigger by being able to step through it in the debugger.
Does anyone know if it’s possible to configure Lazarus or use a specific debugging technique to step into Assert()? Or is there a way to see more context about the failed assertion beyond the termination message? What would be ideal is to be able to single-step through Assert() and any related code.
A simple code example is below that demonstrates the problem.
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit Unit1; {$mode objfpc}{$H+}{$ASSERTIONS ON} // or equivalently {$C+} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls; type { TForm1 } TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private public end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TestDivision(a, b: Integer);var result: Integer;begin // Assert that the denominator is not zero before dividing Assert(b <> 0, 'Error: Division by zero!'); result := a div b; WriteLn(a, ' divided by ', b, ' equals ', result);end; procedure TForm1.Button1Click(Sender: TObject);begintry WriteLn('Testing division:'); TestDivision(10, 2); // Works fine TestDivision(10, 0); // Will trigger assertion failure except on E: Exception do WriteLn('Exception: ', E.Message); end;end; end.
Thaddy:
I would first get rid of using a plain exception if what you want is a specific EAssertionFailed exception.
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.Button1Click(Sender: TObject);begintry WriteLn('Testing division:'); TestDivision(10, 2); // Works fine TestDivision(10, 0); // Will trigger assertion failure except on E: EAssertionFailed do WriteLn('Exception: ', E.Message)else raise;// it is not an assertion. end;end; or something along that line;
Joanna from IRC:
Aruna and I were discussing assert () in chat.
Neither of us could step into it. I don’t know if it’s the fault of the gdb or assert is intentionally off limits?
Hovering over assert () doesn’t allow me to click on link to the source code like other things do.
When I tried to use assert in my project it does indeed stop the program with a dialog giving the line number of error and a gump to choose break or continue. Break takes me to spot where error occurred which Is good.
If I continue there is another gump for abort or risk data corruption.
So for debugging I guess it works ok but why am I not allowed to trace into it to see what it’s doing? I want to see how it gets the line number of error and such.
I have opted to use my own version of error checking that shows message and halts because assert requires too much gump clicking %)
Martin_fr:
What do you mean "step into assert"?
If you indeed want to see what assert itself does, then you need to build an fpc (an rtl) with debug info. (e.g. using fpcupdeluxe).
It is in system.inc
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---Procedure fpc_assert(Const Msg,FName:Shortstring;LineNo:Longint; ErrorAddr:Pointer); [Public,Alias : 'FPC_ASSERT']; compilerproc;begin if codepointer(AssertErrorProc)<>nil then AssertErrorProc(Msg,FName,LineNo,ErrorAddr) else HandleErrorAddrFrameInd(227,get_pc_addr,get_frame);end;
Mind that this is an intrinsic. As you can see the boolean result of the condition is not in the parameters => that code is inlined into your calling procedure. So the above is only called, if the condition fails.
Afaik it then depends. If any unit in your app (including recursively any unit you used) uses "SysUtils then it throws an exception.
And if you want you can catch that exception.
Most of the time the assert is simply used to alert of the error, and then meant to stop the exe.
Otherwise use "if ... then raise exception.create();"
MarkMLl:
I checked earlier (since that was my first thought), and even if FPC is built with full debugging the IDE doesn't step into Assert().
Presumably this is because- as you say- Assert() is a compiler/RTL intrinsic. I didn't check whether setting a breakpoint inside the RTL would do it.
MarkMLl
Navigation
[0] Message Index
[#] Next page