Boost logo

Boost :

From: Mario Contestabile (marioc_at_[hidden])
Date: 2000-05-28 10:23:13


Re-Throwing the last exception in your structured Exception handler, I've
never seen that idiom.
With Visual C++, a catch(...) handler traps all exceptions regardless of
whether they were generated by a C++ throw or by the os. Here is your applet
re-organised to use MSVC's translator functionality, and a catch all clause.

See
http://msdn.microsoft.com/library/devprods/vs6/visualc/vccore/_crt__set_se_t
ranslator.htm
http://msdn.microsoft.com/library/devprods/vs6/visualc/vccore/_core_exceptio
n_handling_differences.htm
for a good explanation.

In my apps, I always use SetUnhandledExceptionFilter(), so when the app dies
I obtain the address (in_ExceptionInfo->ExceptionRecord->ExceptionAddress) &
the cause (in_ExceptionInfo->ExceptionRecord->ExceptionCode), and give the
user the option of uploading that info to me. Although other os' may have
such translator functionality, I prefer to have straightforward catch
clauses throughout the code, and leave such os tricks in the implementors
hands.

Mario Contestabile
MarioC_at_[hidden]

#include <iostream>
#include <windows.h>

class SE_Exception {
private:
    SE_Exception() {}
    SE_Exception( SE_Exception& ) {}
    unsigned int nSE;
public:
    SE_Exception(unsigned int n) : nSE(n) {}
    ~SE_Exception() {}
    unsigned int getSeNumber() { return nSE; }
};

void structured_exception_translator(
     unsigned int exception_code, EXCEPTION_POINTERS* pExp)
{
    UnhandledExceptionFilter(pExp);
    throw SE_Exception(exception_code);
}

struct X { ~X() { std::cout << "~X" << std::endl; } };

void crash()
{
    *((char*)0) = 0;
}

void crash_indirectly()
{
    X x;
    crash();
}

int main()
{
   try {
       crash_indirectly();
   }
   catch(...){}

   _set_se_translator(structured_exception_translator);

   try {
       crash_indirectly();
   }
   catch( SE_Exception e ) {}
}

----- Original Message -----
>
> The problem: This applies to programs generated by all compilers using
> Microsoft-compatible EH when run outside a debugger. I plan to write a
longer
> exposition, but I thought I should post this quickly.
>
> ----------
>
> #include <iostream>
>
> struct X { ~X() { std::cout << "~X" << std::endl; } };
>
> void crash()
> {
> *((char*)0) = 0;
> }
>
> void crash_indirectly()
> {
> X x;
> crash();
> }
>
> int main()
> {
> try {
> crash_indirectly(); // You never find out about this crash
> }
> catch(...) { }
>
> try {
> crash_indirectly(); // When post-mortem debugging starts,
> } // X::~X has already run (twice).
> catch(...) {
> throw;
> }
> }
>
> -------------
>
> The solution:
>
> #include <windows.h>
> void structured_exception_translator(
> unsigned int exception_code, EXCEPTION_POINTERS* pExp)
> {
> UnhandledExceptionFilter(pExp);
> throw; // magic!
> }
>
> static void (*saved_translator)(unsigned, EXCEPTION_POINTERS*)
> = _set_se_translator(structured_exception_translator);
>
> -------------
>
> The line labelled "magic!" above is still a bit of a mystery to me.
Without it,
> the debugger appears to re-start the program in the
> structured_exception_translator, but the program immediately continues
just as
> in the first example (except that the debugger has been invoked). If
anyone has
> insight into this, I'd appreciate it. I'm sure it's a nitty-gritty Windows
> thing, the sort of thing I try to avoid and had to muck about in too much
> already to get this far ;). I plan to write a short article for the C++
Report
> about this once I get that final detail worked out.
>
> -Dave


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk