views:

158

answers:

3

In MSVC, how can I make any unhandled C++ exception (std::runtime_error, for instance) crash my release-compiled program so that it generates a dump with the full stack from the exception throw location?

I have installed NTSD in the AeDebug registry and can generate good dumps for things like memory access violation, so the matter here comes down to crashing the program correctly, I suppose.

Thanks in advance.

A: 

SetUnhandledExceptionFilter and DebugBreak should probably do the job.

Edit: oops, rereading, you want to deal with uncaught C++ exceptions. That would be a bit trickier to do well -- by the time you (normally) get wind of a C++ exception, it's already unwound the stack back to the level of the handler. You don't have any real way to know an exception has been thrown until a catch is invoked, but by then the stack has been unwound.

Jerry Coffin
The set_terminate() function from MSCVRT should do the trick, but I can't get it to work: my handler (which calls RaiseException() and makes the program crash) is never called.
Jorge Vasquez
A: 

Look into using the Windows Debugger.
Windbg – wraps KD and NTSD with a decent UI.
Also check out ADPlus that comes with the Windows Debugger.

Here is a good place to start learning how to use it.

Zamboni
Using the debugger is fine, but that can't be done on the unattended environment the program is running. See, this is a production environment: if there is a problem, the service crashes and will be restarted. I really need a crash dump to perform post-mortem analysis later on. I also need this information on the collected by Windows Error Reporting which I will get later on.
Jorge Vasquez
The Windows Debugger comes with a utility called ADPlus that allowed me to easily gather stack trace for a crash for a release build application. I agree this something that you should only do when trying to track down a crash, not on a continuous basis. For that you need a logging system. Check out all the command switches for ADPlus.
Zamboni
A: 

I finally cracked it down.

  1. Use the set_terminate() function to register a handler for every thread
  2. In you main function(), make it impossible for external DLLs (event Windows') to successfully call SetUnhandledExceptionFilter(). A great article on how to do that here: http://www.debuginfo.com/articles/debugfilters.html#overwrite .
  3. As for the handle itself, it is quite straightforward:
void Terminate()
{
  OutputDebugStringA("Terminate\r\n");
  RaiseException(0xE0000010, EXCEPTION_NONCONTINUABLE, 0, 0);
}

Calling RaiseException() like the above example is enough to make the process crash and produce my mush desired dump.

Just so you know, the problem I was having was:

  1. The IPHelper Windows API loads dynamically another Windows DLL
  2. This DLL uses Windows own version of the C runtime (MSVCRT instead of MSVCRT90)
  3. The new C++ runtime calls SetUnhandledExceptionFilter() on startup to catch C++ exceptions. Since the latest filter for C++ exceptions is the one who gets to call the handle set by set_terminate(), my handle wasn't called.
Jorge Vasquez