Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2025-11

Debugger question

9 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Michael Van Canneyt

Hi

How can I get the actual value of an ansistring from the lazarus debugger ?

- Every value I get is limited to 255 characters

- I can't seem to get rid of the #$0A for embedded newlines etc.

It seems like a simple thing to get, and I tried all windows I could think of: local variables, watch, inspect, evaluate.
None worked as would expect it. So finally I resorted to using writeln(). :/

I must be missing something obvious.

Michael.

Reply by email

Martin Frb
to Michael Van Canneyt

After writing the below, I found the locals window may have some limit (not sure why/how).

But watches should be fine.

Michael Van Canneyt wrote 7 lines
Hi How can I get the actual value of an ansistring from the lazarus debugger ? - Every value I get is limited to 255 characters

That is odd / unexpected. (unless its shortstring, but I guess you wouldn't ask then..)

Are you using FpDebug? Win or Linux?

Which compiler version?
Are you using Dwarf-2 or Dwarf-3?
And, if on Linux, are you sure all your code (including packages/rtl) uses the same (or no debug info)?

Those settings usually only affect if the debugger can distinguish between ansistring and pchar. It shouldn't impact the length.

If FpDebug thinks its a PChar then it will print it with address (by default / can configured)
$12345678^: 'abcd'
versus a string would just print
'abcd'

But even a pchar prints full length for me

If FpDebug, what does
? :length(foo)
report?
https://wiki.freepascal.org/FpDebug-Watches-Intrinsic-Functions#Length(String-or-array)

Can you access chars / substrings further up?
foo[500..900]
?
The display (string vs array) may depend on it being seen as string or pchar.

There is a setting, in "Debugger Backends" property grid: Mem limits. There the max read len can be restricted.
So if your variable contains trash, the debugger doesn't try to allocate 100GB for a string that doesn't exist.

- I can't seem to get rid of the #$0A for embedded newlines etc.

Context menu, copy raw value.

As for watching while debugging, that is currently all assuming single line display (like the watches window / even though there are some multiline, like evaluate, but they don't do that). So while watching, there isn't a display that shows the string as plain text

Reply by email

Michael Van Canneyt
to Martin Frb
Martin Frb wrote
After writing the below, I found the locals window may have some limit (not sure why/how). But watches should be fine.

Maybe we're talking about different things.

I went to watches, and selected 'Copy raw value':

$000000000071A430^: 'with leerlingen as ('#$0A' select distinct'#$0A' LL_ID, IS_ID'#$0A' from'#$0A' leerling'#$0A' (I cut the length, in this window it is indeed full length)

When I choose 'Copy raw value' from the context menu in the grid with values:

- I don't want the #$0A, I want the actual character.

- I also don't want the quotes

- and definitely not the pointer to memory

Maybe I have a complete misunderstanding of what 'raw value' means. For a string, to me that means the actual data of the string, unprocessed.

I expect to be able to copy & paste it and use the value as-is. Similar for pchar/pansichar/pwidechar.

In the above example, copy & paste to a program where I can execute the SQL.

With what I get today, I need to resort to printing it to screen/file to be able to use the value.

Show quoted text 11 lines
On 29/11/2025 17:10, Michael Van Canneyt via lazarus wrote: > > Hi > > How can I get the actual value of an ansistring from the lazarus > debugger ? > > - Every value I get is limited to 255 characters That is odd / unexpected. (unless its shortstring, but I guess you wouldn't ask then..)

It is not shortstring.

Are you using FpDebug? Win or Linux?

linux, fpdebug

Which compiler version?

3.2.2

Are you using Dwarf-2 or Dwarf-3?

Dwarf 3.

And, if on Linux, are you sure all your code (including packages/rtl) uses the same (or no debug info)?

RTL/Packages use the default.

Show quoted text 11 lines
Those settings usually only affect if the debugger can distinguish between ansistring and pchar. It shouldn't impact the length. If FpDebug thinks its a PChar then it will print it with address (by default / can configured) $12345678^: 'abcd' versus a string would just print 'abcd' But even a pchar prints full length for me

It seems to think that it is a pchar then ?

If FpDebug, what does ? :length(foo) report?

'Error: argument not supported at 2: "length("

(and yes, intrinsicprefix is set to colon)

A feature request: Please add a button (maybe a dropdown button) next to the watch expression edit control which shows the available intrinsics: When one is chosen, it inserts it in the watch edit box with the expected number of arguments.

for example

:length()
:pos(,,)

...and position the cursor after the initial (

This way,

a) the user sees what is available. I had no idea that this is available.

b) avoids typing it and making mistakes.

For you, this is likely all 'very obvious', but for average jane or joe, it is not. I'm sure there are many more hidden gems available, but they're not obvious or easily detectable.

Another suggestion:

A 'help' button in the "watch list" screen that shows the below would not go amiss:

https://wiki.freepascal.org/IDE_Window:_Watch_list

It may be a good idea to also add some 'quick links' to the top of that page.

A link to the page you refer to is buried halfway the page, it deserves a more prominent place to make the hidden gems more visible...

Show quoted text 5 lines
Can you access chars / substrings further up? foo[500..900] ? The display (string vs array) may depend on it being seen as string or pchar.

I can, and it prints PChar: len=X (array of characters)...

There is a setting, in "Debugger Backends" property grid: Mem limits. There the max read len can be restricted. So if your variable contains trash, the debugger doesn't try to allocate 100GB for a string that doesn't exist.

I checked, the limits are way above 255.

Show quoted text 7 lines
> - I can't seem to get rid of the #$0A for embedded newlines etc. Context menu, copy raw value. As for watching while debugging, that is currently all assuming single line display (like the watches window / even though there are some multiline, like evaluate, but they don't do that). So while watching, there isn't a display that shows the string as plain text

Well, I don't need the full length while watching (although that would be useful). I need to be able to copy it to another program and use it there.

To be clear: I think the lazarus debugger is very powerful (definitely more powerful than Delphi's), but at the same time I feel it needs some polishing to be more easily accessible for the non-expert.

...and I believe I belong in the latter category where debugging is concerned.

Michael.

Reply by email

Martin Frb
to Michael Van Canneyt
Michael Van Canneyt wrote 11 lines
I went to watches, and selected 'Copy raw value': $000000000071A430^: 'with leerlingen as ('#$0A'? select distinct'#$0A'??? LL_ID, IS_ID'#$0A'? from'#$0A'??? leerling'#$0A' (I cut the length, in this window it is indeed full length) When I choose 'Copy raw value' from the context menu in the grid with values: - I don't want the #$0A, I want the actual character.

The address at the start means you are watching a PChar. Is your var actually declared as a PChar? If it is declared as string, then maybe try Dwarf3. With Dwarf2 the debugger can't always tell if it is string or pchar.

program Project1; {$Mode objfpc}{$H+}
var a: AnsiString;? p: PChar;
begin
 ? a := 'abc foo'+LineEnding+? ? ? ?'def bar'+#13+ ?'whatever'+#10+? ? ?
 ?'hello world'+LineEnding;
 ? p := pchar(a);
 ? write(a); // breakpoint
end.

If I watch "a", and do "copy raw value" then I get the text, as it would be printed. I.e. no source-code, but text as it would be shown in TMemo.

But with "p" that does not happen. (also not with "^char(a)" / as that also is pchar)

I agree it should be changed. I guess the implementation is based on the fact that pchar is the pointer, not the content. Showing the text content (as for any pointer, any deref-ed content) is a convenience. But for pchar, that should be seen as more essential. Anyway, therefore any of the "copy" will include the pointer => and then it wants to make clear the pointer is not part of the text, so it quotes the text, and quotation means escaping.

Workaround:
? ? ?:substr(p, 0, 9999)

linux,?fpdebug RTL/Packages?use?the?default.

If that is Dwarf-2 then that may cause all strings to misbehave.

On Windows, if I use a type in "unit foo", then the dwarf declaration of the type is repeated (and then exists in the dwarf version of that unit). On Linux, it is just a reference across unit borders , and that means the definition for ansistring is in the rtl, with the dwarf version used there. (Except, if the rtl has no debug info, then the info will be in one or some of the units using ansistring).

If you use only Dwarf-3 then you also should get rid of Watch:? a[1]
Display: PChar: 'b' - String: 'a'

Because if the debugger does not know the type, then it can't tell what a[1] is.

The problem is that strings have no special encoding in the dwarf generated by FPC.
FPC either (iirc dwarf 2) writes them as pchar
or (iirc dwarf 3) as "array of char"

However, when it does the latter, it uses a different order for the dwarf_attributes that describe the array (or some little detail like that). As for the meaning defined by the dwarf standard, this is no difference at all.
But since fpdebug knows the compiler, it can use this. (until someone decides to change it, and either break it, or implements DW_TAG_String or what the name is)

Reply by email

Martin Frb
to Martin Frb
Martin Frb wrote 8 lines
If I watch "a", and do "copy raw value" then I get the text, as it would be printed. I.e. no source-code, but text as it would be shown in TMemo. But with "p" that does not happen. (also not with "^char(a)" / as that also is pchar) I agree it should be changed

Changed in main branch.

Also added nicer formatting for evaluate dlg, and watches detail-pane.

Reply by email

Michael Van Canneyt
to Martin Frb: The address at the start means you are watching a PChar. Is your var actually declared as…
Martin Frb wrote 17 lines
On 30/11/2025 10:54, Michael Van Canneyt via lazarus wrote: > > I went to watches, and selected 'Copy raw value': > > $000000000071A430^: 'with leerlingen as ('#$0A'? select > distinct'#$0A'??? LL_ID, IS_ID'#$0A'? from'#$0A'??? leerling'#$0A' (I > cut the length, in this window it is indeed full length) > > When I choose 'Copy raw value' from the context menu in the grid with > values: > > - I don't want the #$0A, I want the actual character. The address at the start means you are watching a PChar. Is your var actually declared as a PChar? If it is declared as string, then maybe try Dwarf3. With Dwarf2 the debugger can't always tell if it is string or pchar.

I tried unifying the debug info. But it presents a problem:

I can't compile the IDE if the RTL is compiled with dwarf3, I get errors during the linking stage about missing dbg_IUNKOWN symbols (or somesuch)...

> linux,?fpdebug > RTL/Packages?use?the?default. If that is Dwarf-2 then that may cause all strings to misbehave.

See above. Dwarf3 is not an option.

Michael.

Reply by email

Martin Frb
to Michael Van Canneyt
Michael Van Canneyt wrote 9 lines
On Sun, 30 Nov 2025, Martin Frb via lazarus wrote: > > Is your var actually declared as a PChar? If it is declared as > string, then maybe try Dwarf3. With Dwarf2 the debugger can't always > tell if it is string or pchar. I tried unifying the debug info. But it presents a problem:

I know there are errors sometimes if dwarf-2 and 3 are mixed. But I don't know all the cases... And that is a problem that needs to be solved in the compiler.

I found the reduced display length for the locals dlg. I extended that.

In the grids (watches, locals, expect), not affecting the details-pane, nor copy: Text was shortened to 255 chars.
That is now 4096 => you need an extremely wide screen and scrolling, or a tiny font for that...

The reason there is a limit is, that text returned by the debugger can be millions of chars, and that is not sensible to display single line in a grid cell.
But more, the grids to text measure stuff, and with input that long, that can be expensive.

----------

For the stack, the string length are cut off in the debugger, reading from the remote process memory (according to memlimits / so configurable).

In the stack it usually makes no sense to display text (as function param) of greater length.
So the debugger even saves the time for fetching it.

Reply by email

Michael Van Canneyt
to Martin Frb: Changed in main branch. Also added nicer formatting for evaluate dlg, and watches…
Martin Frb wrote 12 lines
On 30/11/2025 12:20, Martin Frb via lazarus wrote: > If I watch "a", and do "copy raw value" then I get the text, as it would be > printed. I.e. no source-code, but text as it would be shown in TMemo. > > But with "p" that does not happen. (also not with "^char(a)" / as that also > is pchar) > > I agree it should be changed Changed in main branch. Also added nicer formatting for evaluate dlg, and watches detail-pane.

One has to love open source. A solution the same day :-)

I can confirm that the 'copy raw value' now copies the string as-is, even with DWARF 2.

Many thanks, this will simplify my (debugging) life really a lot :-)

Michael.

Reply by email

Michael Van Canneyt
to Martin Frb: I know there are errors sometimes if dwarf-2 and 3 are mixed. But I don't know all the…
Martin Frb wrote 22 lines
On 30/11/2025 13:30, Michael Van Canneyt via lazarus wrote: > > On Sun, 30 Nov 2025, Martin Frb via lazarus wrote: > >> >> Is your var actually declared as a PChar? If it is declared as string, >> then maybe try Dwarf3. With Dwarf2 the debugger can't always tell if it is >> string or pchar. > > I tried unifying the debug info. But it presents a problem: I know there are errors sometimes if dwarf-2 and 3 are mixed. But I don't know all the cases... And that is a problem that needs to be solved in the compiler. I found the reduced display length for the locals dlg. I extended that. In the grids (watches, locals, expect), not affecting the details-pane, nor copy: Text was shortened to 255 chars. That is now 4096 => you need an extremely wide screen and scrolling, or a tiny font for that...

No worries, I understand that.

Show quoted text 6 lines
The reason there is a limit is, that text returned by the debugger can be millions of chars, and that is not sensible to display single line in a grid cell. But more, the grids to text measure stuff, and with input that long, that can be expensive.

Yes, I understand the reason for the limitations.

That is why I think only the 'Copy value' function needs to give the actual length...

Michael.

Reply by email