guidelines on portable 'catch(...)' usage

hi there, I'v recently run into a problem with 'catch(...)' on MSVC 7.1, where a segmentation fault resulted in a 'first-class exception' (!) that was caught by 'catch(...)' even though the stack wasn't unwound. My first reaction was to abandon the use of 'catch(...)' entirely, replacing it with a more specific equivalent (which I believe to be better practice anyways). However, browsing some boost code I now find other people using such catch-all statements, and so I'd like to get your feedback on how to use it portably. Are my findings false concerning MSVC's highjacked use of C++ exceptions for program errors (i.e. POSIX' equivalent of signals) ? Thanks, Stefan

"Stefan Seefeld" wrote:
I'v recently run into a problem with 'catch(...)' on MSVC 7.1, where a segmentation fault resulted in a 'first-class exception' (!) that was caught by 'catch(...)' even though the stack wasn't unwound. ... I'd like to get your feedback on how to use it portably. Are my findings false?
No, it is behavior of MSVC by default. This compiler has switch not to map Win32 exceptions into C++ ones. /Pavel

Pavel Vozenilek wrote:
"Stefan Seefeld" wrote:
I'v recently run into a problem with 'catch(...)' on MSVC 7.1, where a segmentation fault resulted in a 'first-class exception' (!) that was caught by 'catch(...)' even though the stack wasn't unwound. ... I'd like to get your feedback on how to use it portably. Are my findings false?
No, it is behavior of MSVC by default.
This compiler has switch not to map Win32 exceptions into C++ ones.
VC++ never maps platform exceptions into C++ exceptions unless you specifically write code to do it (using __set_se_handler). What it does do is catch platform exceptions with catch(...). This is generally acknowledged to be A Bad Thing, unfortunately there's no way you can make catch(...) not catch platform exceptions with VC7.1. Using VC7.1 it's only "safe" to catch platform exceptions if you compile with /EHa (the default is /GX which is equivalent to /EHsc). Under VC8 catch(...) will not catch platform exceptions in code compiled with /EHs, while code compiled with /EHa will retain the behavior it has now. If you want to use catch(...) in VC++ code and NOT translate platform exceptions into C++ exceptions, your only real choice is to use __set_se_handler to set a "handler" that terminates the program when a platform exception is raised. -cd

Carl Daniel wrote:
If you want to use catch(...) in VC++ code and NOT translate platform exceptions into C++ exceptions, your only real choice is to use __set_se_handler to set a "handler" that terminates the program when a platform exception is raised.
It is even possible to rely on the default handler which invokes the debugger. You simply throw the exception from the se_handler. void se_trans(unsigned int i, _EXCEPTION_POINTERS *p) { throw; } Call #pragma warning(disable:4535) _set_se_translator(se_trans); #pragma warning(default:4535) in main(). The pragma disable the warning that the application has to be compiled with asynchronous exception model. But this is irrelevant if you just rethrow the exception and the default handler terminates the application anyway. Hajo

Stefan Seefeld wrote:
hi there,
I'v recently run into a problem with 'catch(...)' on MSVC 7.1, where a segmentation fault resulted in a 'first-class exception' (!) that was caught by 'catch(...)' even though the stack wasn't unwound.
(Nit: Are you sure it wasn't "first chance" exception.) I don't think it is possible to provoke a seg fault without attempting an illegal pointer dereference. (Guard page faults for growing the stack are handled transparently by the kernel.) Therefore, I'm inclined to think that "So don't do that." is the appropriate (if unsympathetic) response.
My first reaction was to abandon the use of 'catch(...)' entirely, replacing it with a more specific equivalent (which I believe to be better practice anyways).
However, browsing some boost code I now find other people using such catch-all statements, and so I'd like to get your feedback on how to use it portably.
If your code is portable, then catch (...) is the only way to deal with the fact that not everything is derived from std::exception. I see nothing wrong with it.
Are my findings false concerning MSVC's highjacked use of C++ exceptions for program errors (i.e. POSIX' equivalent of signals) ?
MSVC's implementation of POSIX signals may well be incompatible with their implementation of catch(...). Come to that, it is probably incompatible with Win32's SEH. Er, so that would be just plain broken then? That tells you how much MS care about POSIX signals. However, avoiding catch(...) strikes me as quite a considerable loss, whereas avoiding POSIX signals in Win32 software (the only thing that MSVC targets) strikes me as hardly any loss at all. If we are considering portable code, we are only considering manually raised signals. They must be almost unheard of in C++ code and fairly uncommon even in the C code that we (nearly) all have to work with.

Ken Hagan wrote:
If your code is portable, then catch (...) is the only way to deal with the fact that not everything is derived from std::exception. I see nothing wrong with it.
Shouldn't all exceptions in boost derive (directly or in most cases indirectly) from std::exception? IIRC discussions from comp.lang.c++.moderated (about "technology stolen by Andrei Alexandrescu from Yasland, ie. yet another std::vector<> implementation"), there was consensus that catch(...) is bad thing. B.

Bronek Kozicki wrote:
Ken Hagan wrote:
If your code is portable, then catch (...) is the only way to deal with the fact that not everything is derived from std::exception. I see nothing wrong with it.
Shouldn't all exceptions in boost derive (directly or in most cases indirectly) from std::exception?
Yes, but exceptions do originate from non-boost code.
IIRC discussions from comp.lang.c++.moderated (about "technology stolen by Andrei Alexandrescu from Yasland, ie. yet another std::vector<> implementation"), there was consensus that catch(...) is bad thing.
There is no such consensus. catch(...) is only bad when it's not a catch(...), or when you don't really need a catch(...).

Bronek Kozicki <brok@rubikon.pl> writes:
Ken Hagan wrote:
If your code is portable, then catch (...) is the only way to deal with the fact that not everything is derived from std::exception. I see nothing wrong with it.
Shouldn't all exceptions in boost derive (directly or in most cases indirectly) from std::exception?
IIRC discussions from comp.lang.c++.moderated (about "technology stolen by Andrei Alexandrescu from Yasland, ie. yet another std::vector<> implementation"), there was consensus that catch(...) is bad thing.
If you're interpreting my remarks (in part) I don't agree that it's bad in general. On some platforms it's best avoided, so in portable code it's best avoided, too. http://tinyurl.com/4f8ql -- Dave Abrahams Boost Consulting http://www.boost-consulting.com
participants (8)
-
Bronek Kozicki
-
Carl Daniel
-
David Abrahams
-
Hajo Kirchhoff
-
Ken Hagan
-
Pavel Vozenilek
-
Peter Dimov
-
Stefan Seefeld