Wednesday, March 23, 2011

get stack trace when exception is thrown

Hi,

I am now debugging a program that utilizes many different threads.

there is an exception that is thrown from time to time. the problem is that there is no way to know what thread caused the problem...

does anyone know an easy way to get the stack trace after the exception is thrown? I thought about simply writing a debug messages but it is going to be a huge :-) i guess there are much better techniques than this one ...

I'm using visual studio 2008 - native c++ project....

From stackoverflow
  • The exception itself has the property StackTrace... so you just need return the ToString( ).

    But I belive your problem is more like how to catch a random exception. If it is so, what I do is put all the main code within a try/catch. I really not so sure if the exception is thrown in other thread, it this technique will work.

    You should catch also an ApplicationExeption, that is not derived from Exception.

    Timo Geusch : ofer mentions that his project is a native C++ project. I might be wrong but your suggestion is for .NET, right?
    Len Holgate : Not in C++ it doesn't...
    Romias : Yeap... my mistake... thought you where in .NET
  • Unless I'm very much mistaken, you need to know which thread triggered the exception in order to use the Visual Studio debugger's call stack view, which is obviously the catch-22 situation you're in at the moment.

    One thing I would try is to see if you can get the debugger to break when the exception is thrown (using Debug > Exceptions). You'll have to explicitly enable this, but if you know what type of exception is thrown, this might allow you to work out where it's thrown.

    Other than that, putting a breakpoint in the constructor of the exception (if it's one of your own) should also allow you to work out where it's triggered from.

    If those methods don't work for you I'd be looking at the debug messages as you already suggested.

  • Can you use Exceptions dialog (Debug | Exceptions... menu item, or Ctrl+Alt+E or Ctrl+D E, depending on your keyboard bindings) to break the running code into debugging at the moment the specific exception is being thrown?

  • This library looks like it fits the bill:

    http://www.codeproject.com/KB/threads/StackWalker.aspx

    Jochen Kalmbach looks to have done a very thorough job of wrapping the complexity of the low-level dbghelp.dll interface.

  • If you can't get a debugger to catch what is happening... and you can't printf the stack trace and thread...

    My guess is that you will have to put in some good ol' elbow grease and hard work. Start by understanding the system. Once you understand the system, try splitting the system into two halfs. The part that works and the part that doesn't work. Then keep trying to do that until you drill down to the problem.

    When you drill down far enough try surrounding the suspicious code with try/catch... hopefully then you can use the debugger to stop the execution and see what is happening.

  • You could put a break point in the exceptions constructor (i.e. the object you are about to throw).

    This of course assumes you have a common exception hierarchy.

  • This is trivially easy with WinDBG, which is free from Microsoft. You will also want to install symbols for your version of Windows, if you don't have them already.

    Simply setup WinDBG as your Crash Dump tool. I use this registry setting: (You may wish to edit the paths)

    Sample: CrashDumpSettings.reg:

    Windows Registry Editor Version 5.00
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
    "Auto"="1"
    "Debugger"="C:\\progra~1\\debugg~1\\cdb.exe -p %ld -e %ld -g -y SRV*c:\\mss*http://msdl.microsoft.com/download/symbols -c \"$<c:\\Dumps\\CrashDump.cdbscript\""
    

    Here is what your CrashDump.cdbscript might look like: (This is basically what I use... Edit the paths as appropriate.)

    Sample: CrashDump.cdbscript:

    .sympath+ c:\windows\symbols;c:\some\path\to\symbols\for\your\project
    
    as /c CrashFirstModule .printf "%mu", @@c++((*(ntdll!_LDR_DATA_TABLE_ENTRY**)&@$peb->Ldr->InLoadOrderModuleList.Flink)->BaseDllName.Buffer) 
    
    .logopen /t c:\dumps\${CrashFirstModule}_process.log
    .kframes 100
    !analyze -v
    ~*kv
    lmv
    .logclose
    
    .dump /mhi /u /b c:\dumps\${CrashFirstModule}_mini.cab
    .dump /mhia /u /b c:\dumps\${CrashFirstModule}_full.cab
    
    q
    

    And you get a nice log file and some dumps you can use to view the state of the process when the exception happened with WinDBG. The log file will have analysis of the error that occurred, including the line of code that caused the error. It will also list the call-stack for each thread. In the call stack listing, the thread with the # next to it's number is the one that caused the exception. There is a TON of information in these files. I recommend picking up Debugging Applications for Microsoft .Net and Microsoft Windows by John Robbins. It's a great book on Debugging, even if it's from a few years ago. You can get it from Amazon for about $20.00.

    ceretullis : +1 great answer!

0 comments:

Post a Comment