www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 11014] New: call stack not displayed when exception is thrown

http://d.puremagic.com/issues/show_bug.cgi?id=11014

           Summary: call stack not displayed when exception is thrown
           Product: D
           Version: unspecified
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: VisualD
        AssignedTo: nobody puremagic.com
        ReportedBy: r.sagitario gmx.de



PDT ---
original report: http://www.dsource.org/projects/visuald/ticket/13

reported 08/24/10 07:47:17 by rndgen for version 0.3.15
enhancement in Debugger

As the title says an incorrect call stack is shown when a user defined
exception is thrown. This error does not appear on hardware exceptions(like
dereferencing null pointers).
Test case:
import std.stdio;
void func1() {

    func2();

}
void func2() {

    //int *p=null;
    //*p=32;
    throw new Exception("msg");

}
void main() {

    func1();

}
To get the call stack the "Thrown" checkbox for win32 exceptions must be set in
the Debug->Exceptions... menu, because the D runtime catches all unhandled
exceptions.
I'm using VS2008 shell with Visuald 0.3.15 on WinXp? and dmd 1.062.

Comment 1: 08/24/10 14:22:59  by sagitario

I haven't used D1 much, but for D2, you don't get good call stacks with the
release version of phobos, because there are no stack frames that the debugger
can follow. Often what you see is _dthrow and then the function that called the
function that has thrown the function.
It's way better if you use a debug build of phobos.

Comment 2: 09/04/10 06:26:53  by rndgen

I did as you suggested, and recompiled phobos with debug information, however
this did not solve the problem. The test results for both D1 and D2:
The '->' indicates where the program stopped according to the debugger.
Although you only mentioned compiling phobos in debug mode, I tried compiling
druntime too, but that only made things worse, and wheter phobos is with or
without debug info made no difference.
D2 call stack with release druntime+debug phobos (same as release
druntime+release phobos):

    kernel32.dll!7c812a5b()         
    [Frames below may be incorrect and/or missing, no symbols loaded for
kernel32.dll]        
    kernel32.dll!7c812a5b()         
    debuggertest.exe!object traceContext()  + 0x14 bytes        C++
    debuggertest.exe__d_throw 4()  + 0x14 bytes        C++

->        debuggertest.exe!main func1()  Line 5        C++

    debuggertest.exe!_Dmain()  Line 14 + 0x5 bytes        C++
    debuggertest.exe!rt dmain2 main runMain()  + 0xc bytes        C++
    debuggertest.exe!rt dmain2 main runAll()  + 0x2e bytes        C++
    debuggertest.exe!_main()  + 0x13c bytes        C++
    debuggertest.exe!_mainCRTStartup()  + 0xa9 bytes        C++
    kernel32.dll!7c816fd7()         

D2 call stack with debug druntime+debug phobos:

    kernel32.dll!7c812a5b()         
    [Frames below may be incorrect and/or missing, no symbols loaded for
kernel32.dll]        
    kernel32.dll!7c812a5b()         
    debuggertest.exe!object traceContext()  Line 1219        C++
    debuggertest.exe!object Throwable <span class="underline">ctor()  Line 1137
+ 0x7 bytes        C++
    debuggertest.exe!object Exception ctor()  Line 1226 + 0x11 bytes        C++
    0012fdc4()        
    debuggertest.exe!rt dmain2 main tryExec()  Line 348 + 0xb bytes        C++
    debuggertest.exe!rt dmain2 main runAll()  Line 414 + 0x11 bytes        C++
    debuggertest.exe!rt dmain2 main tryExec()  Line 348 + 0xb bytes        C++

->        debuggertest.exe!main(int argc=1, char * * argv=0x00a303c4)  Line 430
       C++

    debuggertest.exe!_mainCRTStartup()  + 0xa9 bytes        C++
    kernel32.dll!7c816fd7()         

D1 call stack (both debug and release):
->        kernel32.dll!7c812a5b()         

    [Frames below may be incorrect and/or missing, no symbols loaded for
kernel32.dll]        
    kernel32.dll!7c812a5b()         
    debuggertest.exe__setargv()  + 0x3c6 bytes        C++

I'm reposting the sample code to make sure the line numbers are consistent with
those that are in the above call stacks: (The statements of func2() should be
on separate lines, but I can't get it to display correctly)
import std.stdio;
void func1() {

    func2();

}
void func2() {

    //int *p=null;
    //*p=32;
    throw new Exception("msg");

}
void main() {

    func1();

}
I beleive that a proper call stack on exceptions is very important, so any
advice on how to get this work would be appreciated.

Comment 3: 09/04/10 08:13:41  by sagitario

What you see is what I meant with "the function that called the function that
has thrown the function".
This is caused by _d_throw 4 not having a proper stack frame that the debugger
can follow. You can create it by adding option "-S" to the rule to make deh.c
in win32.mak of druntime. It should look like this:
 deh.obj : src\rt\deh.c
    $(CC) -c $(CFLAGS) -S src\rt\deh.c


It even works for the release library. I haven't tested D1, though.
Thanks for insisting on a fix, I have always been annoyed by this, too. :-)
I'll try to get this into the official druntime makefile.

Comment 4: 09/12/10 22:36:06  by rndgen

Hehe, no problem on the insisting :).
Anyway while this -S option fixes the above test case, I found another case
which does not show a proper call stack:
void func3() {

    int[] arr=[0, 1];
    arr[15]=4;

}
The problem is probably similar to the previous one, but I could not get it to
work. I am completely unfamiliar with debug information and related stuff
though.

Comment 5: 09/13/10 02:36:49  by sagitario

Looks good to me. Do you see the onRangeError function on the stack? In a
release build, it might not come with a correct stack frame. I tried the dmd
2.048 release, and it worked. Are you using some optimizations?
Can you show the displayed call stack?

Comment 6: 09/13/10 11:16:27  by rndgen

I'm using 2.047 because 2.048 has some critical regression.
These are the compiler options I use for druntime:
DFLAGS=-g -nofloat -w -d -Isrc -Iimport
CFLAGS=-g
+the additional -S flag for deh.c
The compiler options for phobos:
DFLAGS=-g -nofloat -w -d
CFLAGS=-g -mn -6 -r
I'm using dmc 8.52.
With these settings this is the call stack I get for func3():
->        kernel32.dll!7c812a5b()         

    [Frames below may be incorrect and/or missing, no symbols loaded for
kernel32.dll]        
    kernel32.dll!7c812a5b()         
    debuggertest.exe___SI?%<span
class="underline">_heap32_multpool_cpp4106907224_()  + 0xb bytes        C++
    ffffffff()        



Interestingly the func1() call stack which worked in a release build with -S
now shows an incorrerct call stack too:
->        kernel32.dll!7c812a5b()         

    [Frames below may be incorrect and/or missing, no symbols loaded for
kernel32.dll]        
    kernel32.dll!7c812a5b()         
    debuggertest.exe!object traceContext()  Line 1219        C++
    debuggertest.exe!object Throwable <span class="underline">ctor()  Line 1137
+ 0x7 bytes        C++
    debuggertest.exe!object Exception ctor()  Line 1226 + 0x11 bytes        C++
    0012fdc4()        
    debuggertest.exe!rt dmain2 main tryExec()  Line 348 + 0xb bytes        C++
    debuggertest.exe!rt dmain2 main runAll()  Line 414 + 0x11 bytes        C++
    debuggertest.exe!rt dmain2 main tryExec()  Line 348 + 0xb bytes        C++
    debuggertest.exe!main(int argc=1, char * * argv=0x00a403c4)  Line 430      
 C++
    debuggertest.exe!_mainCRTStartup()  + 0xa9 bytes        C++
    kernel32.dll!7c816fd7()         

With the release build I get this call stack for func3():
->        kernel32.dll!7c812a5b()         

    [Frames below may be incorrect and/or missing, no symbols loaded for
kernel32.dll]        
    kernel32.dll!7c812a5b()         
    debuggertest.exe__d_newclass()  + 0x95 bytes        C++
    debuggertest.exe!_mainCRTStartup()  + 0xa9 bytes        C++
    kernel32.dll!7c816fd7()         

I checked the dmc options and those are not optimiziations.

Comment 7: 09/14/10 03:22:45  by sagitario

I just noticed that it works for me because I have debug symbols for the
windows DLLs (kernel32.dll) from the Microsoft Symbol Server. Without these, I
get unusable resluts similar to yours.
To enable them, add http://msdl.microsoft.com/download/symbols
(http://msdl.microsoft.com/download/symbols) to the
tools->Options->Debugging->Symbols settings.

Comment 8: 09/14/10 03:51:30  by rndgen

I will try that, however I'm interested why this can't be done normally. (I'm
probably used to everything working out of the box for C++). Is it a
fundamental limitation of D? In D the stack is not properly unwound on
irrecoverable exceptions so I'm guessing it might be caused by this.

Comment 9: 09/15/10 09:39:32  by rndgen

With these external dll's now debugging works perfectly for me too, however it
would be worthwhile to find out why they are necessary.

Comment 10: 09/15/10 13:36:11  by sagitario

As we are using the C++ debugger we might need to mimick what the C++ runtime
does (if the debugger does not have a special way to detect the VC runtime
library). The problem will probably disappear with the mago debugger.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Sep 11 2013