Here is my problem. I have an unmanaged C++ application that occasionally has an unhandled C++ exception. Following good debugging practices I have the PDBs installed on the target machines that demonstrate the problem. Under normal circumstances when an exception occurs Doc Watson will log the information I need (like call stack) to duplicate the problem. Doc Watson is properly configured and works for general exceptions like Win32 exceptions.
However for C++ exceptions that aren't handled Doc Watson is never invoked. Now looking into this some more I realized that abort is being called which will display the standard "your program has a problem" dialog and then close the app. Supposedly under VS2005 it should also invoke Doc Watson (because abort_behavior is set to _CALL_REPORTFAULT). However this doesn't happen. I've explicitly set this flag in my code and it has absolutely no effect. Doc Watson absolutely refuses to be displayed. The best I can get is the Windows Error Reporting dialog to show up with the Debug option when I explicitly disable _WRITE_ABORT_MSG and enable _CALL_REPORTFAULT. However try as I may Doc Watson won't generate a log.
Anybody have any idea how I can get Doc Watson to generate a log when an unhandled C++ exception occurs. Here is my sample code that I'm trying to get working properly.
#include
<windows.h>#include <iostream>
void main ( )
{
_set_abort_behavior(0, _WRITE_ABORT_MSG); //T2
_set_abort_behavior(-1, _CALL_REPORTFAULT);
throw "C++ exception"; //T2
//abort(); //TU2
}
Note that commenting out lines T2 and uncommenting lines TU2 does work properly. It almost appears like abort isn't being called in the same manner when an unhandled exception occurs.
Thanks,
Michael Taylor - 2/21/06

Unhandled C++ exceptions and Doc Watson
Ben Jackson
I had configured Dr. Watson to generate a log file, but I did that yesterday when playing with _set_abort_behavior. This morning I added the calls to set_terminate, crashed it, and then removed the calls and ran it again before thinking to look for the log files. Something in this morning's sequence caused it to start generating the log file. And with the PDB file present, the stack trace is wonderful.
The only other thing I can think is that mysteriously the AEDEBUG registry key became configured correctly (but I didn't go into regedit, so how ):
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
"Auto"="1"
"Debugger"="drwtsn32 -p %ld -e %ld -g"
"UserDebuggerHotKey"=dword:00000000
Michael - is your Aedebug key already set this way If not, does this make it work
I'm ecstatic it works on this one box, but I want to know how to enable it on all customer boxes we ship!!
GavinWu
C++ exceptions are enabled for compilation because I require the stack to be unwound and the C++ objects to be properly cleaned up. Here is the entire C++ command line (note that these are the defaults for a new project except for one or two) for the test VS2005 C++ app I gave earlier:
/Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS"
/Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc80.pdb"
/W3 /nologo /c /Wp64 /ZI /TP /errorReport:prompt
For comparison here is the command line for the actual application that is having the problem (in VS2003):
/Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_WIN32_WINNT=0x0500"
/D "WINVER=0x0400" /D "_AFXDLL"
/FD /EHsc /RTC1 /MDd /GS /GR /Yu"stdafx.h"
/Fp".\Debug/SDAT.pch" /Fo".\Debug/" /Fd".\Debug/"
/FR".\Debug/" /W3 /nologo /c /Zi
Thanks,
Michael Taylor - 2/22/06
Guy C.
What is your command line for compilation Specifically I'm wondering about /EH... but I'd like to see your whole command line for compile and link.
Thanks,
Ben
Lee Coward
I did some more digging and it looks like the correct course of action would be to call set_terminate which is the handler for unhandled exceptions. Check:
ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vclang/html/13f09c53-9254-4407-9db9-14e730e047cc.htm
and
ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vcstdlib/html/b949bd45-75ae-4fe8-af2c-f6ce67167d67.htm
in the 2005 installed msdn help.
Helen Feddema
Thanks,
Derek
Pimenta
Thanks,
Michael Taylor - 2/23/06
N.I.C.
If this didn't work, I was going to try having the SE filter signal a worker thread with the exception info so the worker could use MiniDumpWriteDump() to do the dump from within the application. That would have been undesirable though since it would have added complexity.
Here's the sample code:
// UnhandledExceptions.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <eh.h>
class SimpleException
{
public:
SimpleException() { m_nDataMember = 5; };
private:
int m_nDataMember;
};
LONG WINAPI TopLevelExceptionFilter( struct _EXCEPTION_POINTERS * /*a_pExceptionInfo */)
{
printf( "TopLevelExceptionFilter()\n" );
return EXCEPTION_CONTINUE_SEARCH;
}
void TerminateHandler()
{
printf( "TerminateHandler()\n" );
}
void Sub4()
{
bool l_bThrow = true;
if( l_bThrow )
throw SimpleException();
// This should not be reached. It's just here to test the dump file info.
if( l_bThrow )
throw (int) 5;
}
void Sub3()
{
Sub4();
}
void Sub2()
{
Sub3();
}
void Sub1()
{
Sub2();
}
int _tmain(int argc, _TCHAR* argv[])
{
SetUnhandledExceptionFilter( (LPTOP_LEVEL_EXCEPTION_FILTER) TopLevelExceptionFilter );
// TerminateHandler() is never called because we installed the unhandled exception filter.
// That's OK though because we want the automatic Dr. Watson dump instead.
set_terminate( (terminate_function) TerminateHandler );
Sub1();
return 0;
}
robatdural
1) The default implementation of terminate (of which set_terminate replaces) already calls abort. abort internally checks abort_behavior and reacts accordingly. Therefore calling set_terminate to invoke abort would simply bring up the error dialog twice and still have no other impact nor generate a log.
2) Just to be sure I tried it and it does as I mentioned in point 1. A DW log will not be generated.
The problem, I believe, is that DW (which is set up as the JIT debugger) isn't handling C++ exceptions. Internally it appears that it might only work with Win32 exceptions and therefore simply ignores the debugging request. I believe this because when properly configured I can get the C RTL to provide me the option of connecting to the debugger (DW in this case) but then DW doesn't do anything. Therefore it could be a limitation of DW itself.
Thanks,
Michael Taylor - 2/22/06