The StackTrace function in Delphi 11.2 Alexandria 64 bit returns a different call stack than the 32 bit version.

delphi package - automated exception handling
Post Reply
otcprogrammer
Posts: 3
Joined: Fri Dec 16, 2022 9:25 am

The StackTrace function in Delphi 11.2 Alexandria 64 bit returns a different call stack than the 32 bit version.

Post by otcprogrammer »

Hi,
I found that in Alexandria 64-bit the StackTrace function from the MadStackTrace unit does not return the full stack, comparing to the same function called in the 32-bit application.

In the earlier version of Delphi (10.4) this function worked correctly.
I am attaching a sample project to demonstrate this.
Attachments
Bug.png
Bug.png (136.41 KiB) Viewed 4966 times
Wrong_CallStack_64bit.zip
(90.71 KiB) Not downloaded yet
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: The StackTrace function in Delphi 11.2 Alexandria 64 bit returns a different call stack than the 32 bit version.

Post by madshi »

Your test project does not have madExcept activated/enabled. This is required for madExcept to fully work.

On a side note, inside of a try..except block (directly or indirectly), it's recommended to call "madExcept.GetCrashStackTrace()" instead of "madStackTrace.StackTrace(True)". That will give you a much better stack trace, because the stack trace will point to (and end at) the actual crash location, instead of showing you the location where you called "StackTrace()".
otcprogrammer
Posts: 3
Joined: Fri Dec 16, 2022 9:25 am

Re: The StackTrace function in Delphi 11.2 Alexandria 64 bit returns a different call stack than the 32 bit version.

Post by otcprogrammer »

Sorry, but I need to log the call stack at the moment of a possible crash of the program without forcing the user to take any additional actions on his part, without firing the MadExcept window. Both the madStackTrace.StackTrace() and madexcept.GetCrashStackTrace() functions allow me do this, but only for 32 bits (thanks, madexcept.GetCrashStackTrace() really returns a better call stack). But it also does not work correctly in Alexandria 64-bit. Although Delphi 10.4 Sydney didn't have this problem.
Attachments
Bug_64b.png
Bug_64b.png (63.05 KiB) Viewed 4948 times
OK_32b.png
OK_32b.png (94.31 KiB) Viewed 4948 times
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: The StackTrace function in Delphi 11.2 Alexandria 64 bit returns a different call stack than the 32 bit version.

Post by madshi »

You can activate madExcept but hide the bug report window. Really, madExcept was not designed to be used without being activated. I mean you can try using it that way, but it's not something that is fully supported. Activating madExcept means that madExcept also applies some patches to the RTL to streamline exception handling etc. I'm not 100% sure right now why the 64bit stacktrace only is correct with madExcept activated, but I'm sure there's a good reason for that.
otcprogrammer
Posts: 3
Joined: Fri Dec 16, 2022 9:25 am

Re: The StackTrace function in Delphi 11.2 Alexandria 64 bit returns a different call stack than the 32 bit version.

Post by otcprogrammer »

The point that I must again emphasize is that there was no such issue in Delphi 10.4. Would you please find that good reason that you mentioned and deal with it? Or, am I missing something?
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: The StackTrace function in Delphi 11.2 Alexandria 64 bit returns a different call stack than the 32 bit version.

Post by madshi »

The "good reason" is that in 64bit, if you have try..except blocks, their handling actually overwrites the stack, clearing out important information that is needed for stack tracing.

When madExcept is activated, it hooks deep into the RTL and collects the callstack information whenever an exception is raised (before it's even handled). The callstack information is internally stored until either the exception is handled, or until madExcept becomes active. This allows madExcept to provide you with good stack traces, not allowing the important information to be overwritten.

The only way to "deal with it" is to let madExcept do its job, the way it was designed. What you're doing is basically telling madExcept "you're not allowed to hook into the RTL, but I still want you to provide perfect results". Which is technically not possible.

I'm not sure why this worked better with Delphi 10.4 compared to 11. Maybe the way the memory is structured, there's more stack overwriting happening in Delphi 11. I don't really know. In any case, it works fine if you allow madExcept to do its job properly.
Post Reply