|
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