Created attachment 1710
DMD and LDC2 callstacks for the exception
Exceptions in a piece code like:
void main()
{
throw new Exception("hi");
}
...does not generate a proper stack trace for the exception when debugged with a Visual Studio debugger. The debugger does not break at the correct line (or file) when uncaught exception is triggered.
Debugging the same code built with LDC2 causes the debugger to break at the correct line, but only for x86_64 targets (x86-COFF does not work at all for both DMD and LDC2).
dmd --version:
> DMD32 D Compiler v2.081.1
DMD build command:
> dmd -debug -g -m64 main.d
LDC2 build command:
> ldmd2 -debug -g -m64 main.d
Comment #1 by seweratwork — 2018-07-15T13:11:03Z
I have nothing to add to the initial bug report apart from confirming that I can reproduce it and achieve the same results as the OP. This applies to both DMD and LDC2 and can even be reproduced with other throws such as array out of bounds.
Comment #2 by r.sagitario — 2018-11-10T16:25:13Z
The difference of the call stacks printed by the program and shown in the debugger are caused by "throw" capturing the stack before actually raising the exception. This avoids having to walk a couple of optimized functions without a standard stack frame.
The reason for sometimes no line number showing is that the return address for the call to _d_throwc is actually outside of the function:
--- test.d ----
_Dmain:
00007FF703CF1080 55 push rbp
...
00007FF703CF109F 48 83 EC 20 sub rsp,20h
00007FF703CF10A3 E8 D8 01 00 00 call _d_throwc (07FF703CF1280h)
--- No source file -------
00007FF703CF10A8 CC int 3
00007FF703CF10A9 CC int 3
If you add another function after main and main happens to have a size that is a multiple of 16 bytes, the following function in the binary gets shown in the call stack:
// moved here to keep main short
Exception newException() { return new Exception("hi"); }
void main()
{
long x = 1;
int y = 0;
throw newException();
}
void foo()
{
}
compiled with dmd2.083 via "dmd -g -m64 test.d -L/INCREMENTAL:NO"
--- c:\tmp\d\ex\test.d -------
_Dmain:
00007FF79AFA1080 55 push rbp
00007FF79AFA1081 48 8B EC mov rbp,rsp
00007FF79AFA1084 48 83 EC 10 sub rsp,10h
00007FF79AFA1088 48 C7 45 F0 01 00 00 00 mov qword ptr [x],1
00007FF79AFA1090 C7 45 F8 00 00 00 00 mov dword ptr [y],0
00007FF79AFA1097 48 83 EC 20 sub rsp,20h
00007FF79AFA109B E8 60 FF FF FF call test.newException (07FF79AFA1000h)
00007FF79AFA10A0 48 83 C4 20 add rsp,20h
00007FF79AFA10A4 48 89 C1 mov rcx,rax
00007FF79AFA10A7 48 83 EC 20 sub rsp,20h
00007FF79AFA10AB E8 D0 01 00 00 call _d_throwc (07FF79AFA1280h)
_D4test3fooFZv:
00007FF79AFA10B0 55 push rbp
00007FF79AFA10B1 48 8B EC mov rbp,rsp
00007FF79AFA10B4 5D pop rbp
00007FF79AFA10B5 C3 ret
yields a pretty broken callstack in the debugger and also in the program output:
[email protected](6): hi
----------------
0x00007FF79AFA10B0 in void test.foo() at c:\tmp\d\ex\test.d(13)
0x000001943E261000