I did, but it had no effect.
And I finally found the error. It was a cast of a window procedure pointer to a DWORD instead of LONG_PTR in some code that I missed to update fully to 64 bit.
I ended up using the minidump created by WER and loading it into Visual Studio to get a stack trace. (see
https://docs.microsoft.com/en-us/visual ... dump-files ). For the functions in the Delphi compiled executable, the stack trace just showed memory addresses, of course, no names. But using Delphi's CPU view and goto address feature, I could find out the relevant assembler code, and the source code lines.
This gave me a hint there was a bug when calling DefFrameProc, and I worked my way back from there.
The reason the bug went unseen before, is that on this user's system memory was allocated on high virtual addresses, even for the very first allocations, which is unusual (also on a 64-bit system). MakeObjectInstance from Classes.pas, which calls VirtualAlloc, would always return addresses well below 4GiB, except on this user's system. I am not sure what triggers this behavior, since all the relevant settings in Windows Defender (ASLR etc.) were the same on my VM (which did not show the issue), and the user's system (which did trigger the bug). Yet, disabling ASLR fully "solved" it, and stopped VirtualAlloc from allocating on high memory addresses.
I have found no setting that forces this behavior, that is probably hidden somewhere in the registry. Adjusting the AllocationPreference registry key as shown in
https://jazz.net/forum/questions/230876 ... preference might be an option, but this key did not exist on the user's system, so was not the cause.
While I'd like to recreate the settings that cause this high memory address preferring behavior, I implemented a quick solution: reserving 4GB of memory, at the very start of the process, allows to reproduce this issue on my machine. It's a bit slow, but it works. Maybe there is a better solution.
Edit: there is a similar approach which should be more performant here:
https://randomascii.wordpress.com/2012/ ... made-easy/
Edit2: see also
https://docs.microsoft.com/en-us/cpp/bu ... hentropyva
Just a summary for others who might have a similar problem.
Thanks for your suggestions.
Edit3: turns out the reason why I could not see this issue in madexcept (or any other exception catcher) is that the system called
RaiseFailFastException.
However the documentation also states:
If the WER service is disabled or cannot be started or there is no debugger attached to the process, the process will be terminated.
This function raises a second chance exception. If JIT debugging is enabled, a debugger will attach to the process.
So there might be an opportunity to catch it with a mini debugger appended, and create a stack trace that way. Maybe a future extension for madexcept, but just an idea.