While I am at it, now some credit to Delphi 12:
♡ The debugger is awesome compared to Lazarus. It provides all information and presents it nicely colored and browsable. No "This field is not available due to compiler optimizations" and stuff. You can inspect anything, even if not directly in scope of the current method and properties/fields are named like in the inspector, not like in the source code.
True... Unfortunately. Properties are a problem with FPC debugging.
Though a couple of notes for all those who need workarounds. And some advice.
In many (most) cases (with Lazarus 4.0 / with 3.6 only a small subset works) you can call the getter method of a property. However, you have to know the method name, and type it "MyStringList.GetText()". And enable function calling (global, and on each watches' properties).
You can also (use the "debug inspect" to assemble the watch) watch this
(MyStringList.FList)^[0..MyStringList.FCount-1].FString
And it shows you all entries of a stringlist, without having to call the getter function.
See
https://wiki.freepascal.org/FpDebug-Watches-Intrinsic-Functions#Array_slice_MyArray[n..m]_with_mapping
A word (warning) on function calling.And a word on what (afaik) Delphi does. At least it did, back in the day of Delphi 5, and it is still the same underlying issue.
This was the first thing, that Delphi burnt me with. Really burnt me good.
I had an app that crashed (as I later found because of "Handle" not being created). I debugged it in Delphi, and added "TheControl.Handle" as watch.
And it wouldn't crash in the debugger.
I lost a good bit of time, till I found the answer.
Because "Handle" is a property with getter, the only way for the debugger to show the value, is to call the getter method. But that getter method would actually create the Handle. (unlike my crashing code, that somehow called something that used the handle, but bypassed creation).
So watching any property with getter in Delphi (at least older Delphi, but afaik any Delphi) can modify the state of your debugged app. And the app may behave different in the debugger, and you may not be able to find your bug.
And when this will have been added to FPC then the same danger will be there.
That said, it is still a feature that would be good to have. But anyone using it should be aware, that it is a dangerous feature.
Other than that, I wasn't aware that Delphi colors watches. What is it used for? Some pattern in the data? Or "changed during last step/run"?
"changed during last step" is an my Todo.
And (in a
feeble attempt to even the balance):
- Have you tried to watch a long array in Delphi (say 1000 entries)? What happens if you "unfold" it? Last I asked someone (I don't have Delphi), they got the full list with 1000 rows. Happy scrolling down, if you have more watches below. Lazarus has pagination.
- And we now (4.0) have :flatten (see intrinsic link above) to display linked lists and tree structures. Though again, you have to enter the expression by hand. (maybe in future that can be automated for known types)
I don't know what/if Delphi has for this.
- For types like
TModalResult = low(Integer)..high(Integer);
mrNone = 0;
mrOK = mrNone + 1;
you can now create a value formatter
https://wiki.freepascal.org/IDE_Window:_IDE_Options_-_Debugger_Value-Formatter#Convert_Ordinal_to_name to display the names, instead of numbers.
(Actually, probably could add a pre configured one for TModalResult..., just had not yet thought of that / well, maybe if I find some time)