Is internal catch-clause rethrow standard?

17 views
Skip to first unread message

Alf P. Steinbach

unread,
Jul 10, 2002, 6:44:31 AM7/10/02
to
A few years ago a clever technique for implementing a more-
or-less generic exception filter, transforming exceptions
to std::exception, was suggested in this group (CLC++M),
functionally equivalent to


catch( ... )
{
try
{
throw;
}
catch( TypeA const& x )
{
throw MyStdException( x );
}
catch( TypeB const& x )
{
throw MyStdException( x );
}
// Etc.
catch( ... )
{
throw MyStdException( "Unknown inner exception" );
}
}


At the time there was much discussion about what this technique
"should" be used for, but it all stopped when Andrei pointed out
that Visual C++ 6.0 -- or was it 5.0? -- doesn't support
this construction.

Is internal catch-block rethrow support required by the std?

Note: in practice the inner try-catch block would reside in a
separate function called from the outer catch.

- Alf

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

David Abrahams

unread,
Jul 10, 2002, 3:07:57 PM7/10/02
to

"Alf P. Steinbach" <alf_p_s...@yahoo.no> wrote in message
news:3d2be46c...@news.online.no...

> A few years ago a clever technique for implementing a more-
> or-less generic exception filter, transforming exceptions
> to std::exception, was suggested in this group (CLC++M),
> functionally equivalent to
>
>
> catch( ... )
> {
> try
> {
> throw;
> }
> catch( TypeA const& x )
> {
> throw MyStdException( x );
> }
> catch( TypeB const& x )
> {
> throw MyStdException( x );
> }
> // Etc.
> catch( ... )
> {
> throw MyStdException( "Unknown inner exception" );
> }
> }
>
>
> At the time there was much discussion about what this technique
> "should" be used for, but it all stopped when Andrei pointed out
> that Visual C++ 6.0 -- or was it 5.0? -- doesn't support
> this construction.

That's not quite accurate. VC++6 will compile it, but will generate
incorrect code: the exception object being re-thrown will be destroyed
twice. If you're going to use this idiom with VC6, you need to exercise some
discipline about the way you write your exception classes so that they are
immune to double-destruction. It's generally pretty easy to do that.

> Is internal catch-block rethrow support required by the std?

Yes.

-Dave

Rune Huseby

unread,
Jul 10, 2002, 3:12:17 PM7/10/02
to
On 2002 07.10 12:44, alf_p_s...@yahoo.no (Alf P. Steinbach) wrote:

> A few years ago a clever technique for implementing a more-
> or-less generic exception filter, transforming exceptions
> to std::exception, was suggested in this group (CLC++M),
> functionally equivalent to

[...]

>
>
> At the time there was much discussion about what this technique
> "should" be used for, but it all stopped when Andrei pointed out
> that Visual C++ 6.0 -- or was it 5.0? -- doesn't support
> this construction.

I avoid using catch(...) in VC 6 since it catches _all_ exceptions.
Including NT exceptions like access violations and division by zero. Some
of these exceptions is of such a nature that the application should die
instead of handling it generically.

> Is internal catch-block rethrow support required by the std?

I don't know about this.


--
Rune Huseby

Alexander Terekhov

unread,
Jul 11, 2002, 7:17:59 AM7/11/02
to

Rune Huseby wrote:
[...]

> I avoid using catch(...) in VC 6 since it catches _all_ exceptions.

That's what catch(...) is all about, MS bugs [and SEH 'integration']
aside. If you have implementation that 'supports' ex.specs, try this:

void
operation();

/**/

void
fenced_operation_invocation()
throw(
/* I REALLY >>REALLY<< WANT CATCH THESE EXCEPTIONS *
* AND, PLEASE, >>PLEASE<< IN ANY EVENT, DON'T ADD *
* 'mothers-of-all-exceptions' like std::exception *
* and/or std::bad_exception !!!!!!!!!!!!!!!!!!!!! */
blah,
blahblah
/* etc. */
)
{
operation();
}

/**/
try {
fenced_operation_invocation();
}
catch(...) {

// 'recovers' exception type/info via 'try-rethrow-catch'
handle_fenced_operation_exceptions();

}

Oh, Ah, if/when you meet Abrahams/Sutter/etc., please tell'm that
"implementation-defined" unwinding-to-nowhere for uncaught exceptions
[lack of *mandatory* TWO-PHASE processing] and the 'khm' way how the
standard *requires* unwinding in order to 'detect' ex.specs. violation
on *archaic* setjmp/longjmp 'C-macros' exceptions implementations [w/o
f.ex. handlers-identity registration prior to entering try scopes that
would allow checking/search w/o unwinding] is... well, 'BS', IMHO|sorry.

regards,
alexander.

Allan W

unread,
Jul 12, 2002, 7:16:02 AM7/12/02
to
Alexander Terekhov <tere...@web.de> wrote

> Oh, Ah, if/when you meet Abrahams/Sutter/etc., please tell'm that
> "implementation-defined" unwinding-to-nowhere for uncaught exceptions
> [lack of *mandatory* TWO-PHASE processing] and the 'khm' way how the
> standard *requires* unwinding in order to 'detect' ex.specs. violation
> on *archaic* setjmp/longjmp 'C-macros' exceptions implementations [w/o
> f.ex. handlers-identity registration prior to entering try scopes that
> would allow checking/search w/o unwinding] is... well, 'BS', IMHO|sorry.

I'm having trouble parsing this extremely-long sentence, and not just
because of the random 'quoting' you do. What does this sentence mean?
Specifically:
* Why do you single out "Abrahams/Sutter/etc"
* What is "unwinding-to-nowhere"
* What is TWO-PHASE processing and why should it be *mandatory*
* What is the 'khm' way how
* does try/catch require "handlers-identity registration" prior to
entering try scopes

Sorry if I'm just too dumb to understand... I'd appreciate any
illumnation you can provide.

Alexander Terekhov

unread,
Jul 12, 2002, 10:12:27 PM7/12/02
to

Allan W wrote:
>
> Alexander Terekhov <tere...@web.de> wrote
> > Oh, Ah, if/when you meet Abrahams/Sutter/etc., please tell'm that
> > "implementation-defined" unwinding-to-nowhere for uncaught exceptions
> > [lack of *mandatory* TWO-PHASE processing] and the 'khm' way how the
> > standard *requires* unwinding in order to 'detect' ex.specs. violation
> > on *archaic* setjmp/longjmp 'C-macros' exceptions implementations [w/o
> > f.ex. handlers-identity registration prior to entering try scopes that
> > would allow checking/search w/o unwinding] is... well, 'BS', IMHO|sorry.
>
> I'm having trouble parsing this extremely-long sentence, and not just
> because of the random 'quoting' you do. What does this sentence mean?
> Specifically:
> * Why do you single out "Abrahams/Sutter/etc"

Red herring. Well,

http://groups.google.com/groups?selm=230879.F56DA7E1%40web.de
("protection", "IOW, I believe strongly that...", etc.)

> * What is "unwinding-to-nowhere"
> * What is TWO-PHASE processing and why should it be *mandatory*

http://groups.google.com/groups?selm=3CFB9FF7.76D1109A%40web.de
http://groups.google.com/groups?selm=3CFC6591.870B42A%40web.de
http://groups.google.com/groups?selm=3CFC66B9.4C7B17AC%40web.de
http://groups.google.com/groups?selm=3CC434E6.8FE3804C%40web.de
http://groups.google.com/groups?selm=3CC45475.BF5A69D2%40web.de
http://groups.google.com/groups?selm=08A049.6850244E%40web.de

> * What is the 'khm' way how

http://groups.google.com/groups?selm=3C7633AF.4A08EFBF%40web.de

> * does try/catch require "handlers-identity registration" prior to
> entering try scopes

http://groups.google.com/groups?selm=3C91397A.9FC5F5A4%40web.de
("OK, you probably mean something along the lines of...")

> Sorry if I'm just too dumb to understand... I'd appreciate any
> illumnation you can provide.

HTH.

regards,
alexander.

P.S. http://www.opengroup.org/sophocles/show_mail.tpl?source=L&listname=austin-group-l&id=4300
([Re: abort() and async-signal safety] "...all I want is simply...")

Francis Glassborow

unread,
Jul 13, 2002, 8:44:48 PM7/13/02
to
In article <3D2EDF6C...@web.de>, Alexander Terekhov
<tere...@web.de> writes

Could you please answer the question. I followed the link, and, probably
because of my advanced age induced stupidity, am still none the wiser.


--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

Jim Hyslop

unread,
Jul 13, 2002, 8:47:57 PM7/13/02
to
In article <3D2D495E...@web.de>, tere...@web.de says...

>
> Rune Huseby wrote:
> [...]
> > I avoid using catch(...) in VC 6 since it catches _all_ exceptions.
>
> That's what catch(...) is all about, MS bugs [and SEH 'integration']
> aside.
No, catch(...) is about catching a C++ exception. MSVC allows it to
catch a hardware exception - and this has cost us no end of grief,
because we're writing code that has to run on both Windows and an
embedded system, which does _NOT_ provide structured exception handling.
It wouldn't be such a big deal IF I could turn off MSVC's structured
exceptions, but I can't (easily - yes I know there are ways to do it,
but none of them are particularly easy..

Worse, we recently had a "Pure Virtual Function Called" crash - that
only happened in release mode on the Windows platform, not in debug
mode. Eventually, we tracked it down to code that essentially did this:

class ABC
{
public:
void somePureFunction() = 0;
};

class Concrete : public ABC
{
public:
void somePureFunction();
};

void oops()
{
Concrete * cp = new Concrete;
delete cp;
cp->somePureFunction();
}

In debug mode, the compiler overwrites memory that is deallocated with a
sentinel value (0xDD, IIRC). So when cp got deleted, its vptr got set to
0xDDDDDDDD. When the program tried to read the vtable to look up
somePureFunction, of course it threw an access violation - which was
promptly absorbed by the nearest "catch (...)" statement. In release
mode, though, the memory is simply returned to the heap as-is. By that
time, cp's vptr points to the ABC vtable - which has a pure virtual
function entry.

We cannot eliminate the "catch(...)" handlers - as I said, one of the
platforms for this software is an embedded system that cannot allow
unhandled exceptions.

> If you have implementation that 'supports' ex.specs, try this:

Are there any implementations besides MSVC that support structured
exceptions?

--
Jim

David Abrahams

unread,
Jul 14, 2002, 1:43:14 PM7/14/02
to

"Jim Hyslop" <jhy...@ieee.org> wrote in message
news:MPG.17995092a...@news1.on.sympatico.ca...


> In article <3D2D495E...@web.de>, tere...@web.de says...

> No, catch(...) is about catching a C++ exception. MSVC allows it to


> catch a hardware exception - and this has cost us no end of grief,

<snip>

You can protect yourself from most of these effects with MSVC via this hack:

# pragma warning(push)
# pragma warning(disable:4297)
extern "C" void structured_exception_translator(unsigned int,
EXCEPTION_POINTERS*)
{
throw;
}
# pragma warning(pop)

extern "C" { typedef void (*translator)(unsigned int,
EXCEPTION_POINTERS*); }
translator x = _set_se_translator(structured_exception_translator);

That will keep catch(...) clauses from interfering with structured
exceptions (unless those SEs are themselves thrown from within a catch
block).

> Are there any implementations besides MSVC that support structured
> exceptions?

Metrowerks CodeWarrior does. Better yet, you can use a
"zero-runtime-overhead" C++ EH model which eliminates the egregious
overheads imposed by SEH for C++ exceptions and in which C++ exceptions and
structured exceptions are completely separate beasts.

-Dave

Alexander Terekhov

unread,
Jul 15, 2002, 5:00:36 PM7/15/02
to

Francis Glassborow wrote:
>
> In article <3D2EDF6C...@web.de>, Alexander Terekhov
> <tere...@web.de> writes
> >> * What is the 'khm' way how
> >
> >http://groups.google.com/groups?selm=3C7633AF.4A08EFBF%40web.de
>
> Could you please answer the question.

Follow the link.

We've got three functions -- a(), b() and c(). Function a() specifies
exceptions that it can throw -- throw( a_bad_exception, /* and let's
say */ Lenin, Stalin ). A_bad_exception beast is thrown by unexpected
handler that is set internally (via RAII "activator" object) -- inside
function a().

Function b() doesn't have exceptions specified; it could throw
anything. Function c() specifies throw( c_bad_exception, /* and
let's say */ Gorby ). C_bad_exception beast is thrown by unexpected
handler that is set internally (via RAII object) -- inside function
c(). Function a() calls b(). Function b() calls c().

Now, imagine that function c() throws Gorby. Gorby flies way up the
stack to the a()'s implicit catch(...) handler injected due to a()'s
ex.specs. C()'s unexpected handler flies together with Gorby. Since
Gorby was not specified in the list of exceptions that can be thrown
from a(), our wonderful implicit catch(...) handler will invoke
unexpected handler that was established inside function c() by the
time Gorby was fired. That unexpected handler will throw
c_bad_exception, but THAT exception is also not allowed to propagate
out of a()... and the program will terminate.

Now try to imagine what would happen if c()'s unexpected handler
would be invoked AT GORBY THROW POINT -- inside function c()... It
(i.e. c()'s unexpected handler) would throw c_bad_exception. Function
b() would catch it via its explicit catch() handler and would either
fully "handle" it or throw "something_else". That "something_else"
could then either:

a) be propagated out of b() and a(); if a() doesn't catch it and
if "something_else" is actually Lenin or Stalin or perhaps
a_bad_exception (and if it's EXPECTED on the "higher" level);

b) result in unexpected handler (established by function a())
being invoked at SOMETHING_ELSE THROW POINT -- inside function
b()... and that would throw a_bad_exception, which COULD well be
propagated out of function b() AND a() (again, if it's EXPECTED
on the "higher" level).

Do you see the point? Or am I missing and/or misunderstanding
something?

regards,
alexander.

Michiel Salters

unread,
Jul 16, 2002, 5:34:42 AM7/16/02
to
jhy...@ieee.org (Jim Hyslop) wrote in
news:MPG.17995092a...@news1.on.sympatico.ca:

> In article <3D2D495E...@web.de>, tere...@web.de says...
>>
>> Rune Huseby wrote:
>> [...]
>> > I avoid using catch(...) in VC 6 since it catches _all_ exceptions.
>>
>> That's what catch(...) is all about, MS bugs [and SEH 'integration']
>> aside.

> No, catch(...) is about catching a C++ exception. MSVC allows it to
> catch a hardware exception - and this has cost us no end of grief,
> because we're writing code that has to run on both Windows and an
> embedded system, which does _NOT_ provide structured exception handling.
> It wouldn't be such a big deal IF I could turn off MSVC's structured
> exceptions, but I can't (easily - yes I know there are ways to do it,
> but none of them are particularly easy..

I've found that any exception caught by ... but not by a preceding
std::exception& was an error. That is something I treat like a failed
assert, something the running process can't handle not ignore. The only
strategy is to call in external help, either from other components, the OS
or a (human) operator. SEH exceptions are no exception ( pun not intended )

Regards,
--
Michiel Salters

Alexander Terekhov

unread,
Jul 16, 2002, 5:36:05 AM7/16/02
to

David Abrahams wrote:

[snip undocumented hack -- probably won't work under next "pack", anyway]

BTW, somewhere on the MS site [no link this time -- probably won't show up
without that nice just-a-few-characters-lost phenomenon I've experienced
here recently, anyway]:

"....
#pragma managed
void managed_func(void)
{
try
{
RaiseException(MYEXCEPTION_CODE, 0, 0, 0);
}
catch(CMyException x)
{
}
catch(...)
{
printf("This is invoked since _set_se_translator is not supported when /clr is used\n");
}
}
....
#pragma managed
int main(int argc, char** argv)
{
_set_se_translator(my_trans_func);
// it doesn't matter whether the translator function
// is registered in managed or unmanaged code
managed_func();
unmanaged_func();
return 0;
}
...."

[...]


> Better yet, you can use a
> "zero-runtime-overhead" C++ EH model which eliminates the egregious
> overheads imposed by SEH for C++ exceptions and in which C++ exceptions and
> structured exceptions are completely separate beasts.

IMO, you are /still/ thinking in the "wrong" direction, really.

regards,
alexander.

Matthew Collett

unread,
Jul 16, 2002, 4:37:45 PM7/16/02
to
In article <3D326BB4...@web.de>,
Alexander Terekhov <tere...@web.de> wrote:

> C_bad_exception beast is thrown by unexpected
> handler that is set internally (via RAII object) -- inside function
> c(). Function a() calls b(). Function b() calls c().
>
> Now, imagine that function c() throws Gorby. Gorby flies way up the
> stack to the a()'s implicit catch(...) handler injected due to a()'s
> ex.specs. C()'s unexpected handler flies together with Gorby.

> [...] That unexpected handler will throw

> c_bad_exception, but THAT exception is also not allowed to propagate
> out of a()... and the program will terminate.
>

> alexander.

Not if your RAII is doing its job. Unwinding the stack as you leave
c() will call the RAII object's destructor, which should reset the
unexpected handler to whatever it was before entering c(). The
implicit catch(...) in a() that actually _calls_ the unexpected
handler isn't reached until after this resetting has occurred, so
all should be well.

> Or am I missing and/or misunderstanding something?

Or maybe I am ...


Best wishes,
Matthew Collett

--
The word "reality" is generally used with the intention of evoking sentiment.
-- Arthur Eddington

Hillel Y. Sims

unread,
Jul 16, 2002, 4:53:57 PM7/16/02
to

"Jim Hyslop" <jhy...@ieee.org> wrote in message
news:MPG.17995092a...@news1.on.sympatico.ca...
> No, catch(...) is about catching a C++ exception.

std::exception is the path to nirvana (and robust code).

1) Never use catch(...), especially in portable code.
2) Always derive all custom exception-types from std::exception (or
subclass), without exception.
3) Catch all C++ exceptions (where necessary) via catch (std::exception&),
which is guaranteed to work if rule 2 is followed.

catch (std::exception&) is all about catching all C++ exceptions. catch
(...) is specifically about catching anything the platform might possibly
throw at you (such as access violation) that lives on the same native
runtime mechanism on which C++ exception-handling is implemented, without
any knowledge of its context or type. I have read (hopefully carefully
enough) the standard and found nothing which explicitly requires anything
caught by catch(...) to be only something raised by a C++ "throw"
statement.** All this makes it legal for platforms (eg Windows, Tru64 Unix,
OpenVMS) to implement their C++ runtime conveniently on top of the
OS-native SEH exception mechanism, with the result that all SEH exceptions
can be caught in catch(...) blocks. This makes it actually very deceptively
dangerous to use catch(...) as an attempt at achieving nothrow status (such
as in dtors) or for error protection, because that block is likely to be
executed not just upon throw of a C++ exception, but also upon a fatal
corruption of the program state (such as access violation) which is raised
as an SEH exception. This means it is unknowingly possible that it is
already far too late for any attempt at nothrow or error protection. (Error
correction of that sort of error, if any, must happen explicitly via
platform-specific API code, and should not be attempted by ordinary generic
user code.) Even in a nothrow block, capturing a non-C++ fatal process
exception and continuing normal execution after that point as if nothing bad
actually happened is virtually always a Very Bad Thing (especially if you
try to write out some important data somewhere which is possibly unknowingly
corrupted...).

There is a simple way to write correct nothrow code that does not suffer
from this problem. _All_ C++ exceptions (including custom-defined types of
even minimal complexity) must always be inherited from std::exception (or
subclass). Non-std::exception-derived objects (such as int, or char*) should
simply never be thrown. It is just a bad idea to throw any kind of exception
object other than something derived from std::exception. The ultimate base
class of any custom exception hierarchies should always inherit from
std::exception. If you have a third-party library that uses exception
objects that are not derived from std::exception which you cannot correct,
then you're out of luck; you would need to additionally explicitly use
"catch (library::base_exc&)" in all instances to catch those exceptions.
Substitution of catch(...) is not a suitable strategy, as it opens the door
to receive non-C++ exceptions.

Always derive all exception objects from std::exception (or subclass),
without exception. This is the only way to correctly catch all C++
exceptions in one statement without interfering with OS-specific non-C++
mechanisms.

By following this simple and straightforward convention, it makes it
possible in all cases to correctly catch _all_ (and ONLY) C++ exceptions via
one blanket statement (of course, even this is not necessarily completely
safe all the time, but sometimes it is necessary...). C++ language code
cannot and should not attempt to intervene in OS-native non-C++ exceptions
under the vast majority of circumstances, and especially not inadvertent
circumstances (even to try to do cleanup), as it has no inherent knowledge
of OS-native implementation and context.

Observance of the std::exception-or-bust rule provides an easy way to avoid
any need for or ill concerns resulting from use of catch(...).

>MSVC allows [catch (...)] to
> catch a hardware exception

Exactly why we must all avoid it.

> - and this has cost us no end of grief,
> because we're writing code that has to run on both Windows and an
> embedded system, which does _NOT_ provide structured exception handling.
> It wouldn't be such a big deal IF I could turn off MSVC's structured
> exceptions, but I can't (easily - yes I know there are ways to do it,
> but none of them are particularly easy..
>
> Worse, we recently had a "Pure Virtual Function Called" crash - that
> only happened in release mode on the Windows platform, not in debug
> mode. Eventually, we tracked it down to code that essentially did this:
>

[..]


> of course it threw an access violation - which was
> promptly absorbed by the nearest "catch (...)" statement.

A good example of why it is evil.

[..]


>
> We cannot eliminate the "catch(...)" handlers - as I said, one of the
> platforms for this software is an embedded system that cannot allow
> unhandled exceptions.
>

C++ exception-handling cannot correctly handle exceptions that cannot be
caught by a C++-accessible name. If you need to handle non-C++
platform-specific exceptions, then you must use a non-C++ platform-specific
mechanism. This can indeed make it (very much) more difficult to write
robust C++ code for use on environments that do not fully integrate their
native error-handling mechanisms with the C++ exception-handling mechanism.
However, as clearly displayed by your problem above, catch(...) is certainly
not the path to achieving robust high-availability code.


> Are there any implementations besides MSVC that support structured
> exceptions?

Tru64 Unix, OpenVMS, Metrowerks.

thanks,
hys

**Even if that statement is not 100% correct, or in some cases you can
completely disable SEH/C++ interaction via non-portable #pragma or
compile-flag, I can imagine a situation involving a special platform-native
private C++ exception type, _not_ inherited from std::exception, that is
inaccessible to user code and only the OS can catch it by name (eg, to
represent a fatal process error for an OS written with C++). User code would
only be able to interact with this special exception via catch(...), subject
to all the same problems described above.

--
Hillel Y. Sims
FactSet Research Systems
hsims AT factset.com

Francis Glassborow

unread,
Jul 16, 2002, 5:04:06 PM7/16/02
to
In article <3D326BB4...@web.de>, Alexander Terekhov
<tere...@web.de> writes
>

>Do you see the point? Or am I missing and/or misunderstanding
>something?

Yes, you have been twice asked what 'khm' stands for. The first time you
gave a link that does not appear to answer the question and this time
you have provide two screen fulls that still does not appear to answer
the question.

--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Jim Hyslop

unread,
Jul 17, 2002, 6:33:26 AM7/17/02
to
In article <XBNY8.48163$6r.15...@news4.srv.hcvlny.cv.net>,
use...@phatbasset.com says...

>
> "Jim Hyslop" <jhy...@ieee.org> wrote in message
> news:MPG.17995092a...@news1.on.sympatico.ca...
> > No, catch(...) is about catching a C++ exception.
>
> std::exception is the path to nirvana (and robust code).
:=)

[...]


> I have read (hopefully carefully
> enough) the standard and found nothing which explicitly requires anything
> caught by catch(...) to be only something raised by a C++ "throw"
> statement.**

Right at the beginning of clause 15: "A handler will be invoked only by
a throw-expression invoked in code executed in the handlers try block
or in functions called from the handlers try block." No throw, no
catch, and anything that causes a handler to be entered without an
explicit "throw" statement is non-conforming.

[moved the footnote up for continuity]

> **Even if that statement is not 100% correct, or in some cases you can
> completely disable SEH/C++ interaction via non-portable #pragma or
> compile-flag, I can imagine a situation involving a special platform-native
> private C++ exception type, _not_ inherited from std::exception, that is
> inaccessible to user code and only the OS can catch it by name (eg, to
> represent a fatal process error for an OS written with C++). User code would
> only be able to interact with this special exception via catch(...), subject
> to all the same problems described above.

I don't agree. From the OS's point of view, the C++ exception handling
scheme is simply another tool for me, the programmer, to handle errors
in my program - a glorified setjmp/longjmp, if you will (remember, this
is from the OS's perspective, not ours).

If the OS is raising an exception that is intended for the OS to catch,
then that exception handling mechanism should be completely independent
of any software error handling. My program should not in any way be able
to intercept exceptions generated by the OS, intended to be received by
the OS, no matter what I do.

> C++ language code
> cannot and should not attempt to intervene in OS-native non-C++ exceptions

So why does the OS force its exceptions into my C++ program?

> >MSVC allows [catch (...)] to
> > catch a hardware exception
>
> Exactly why we must all avoid it.

No, I'd say this is exactly why we should tell MS (via our community
liaison, Herb Sutter, perhaps - Herb, are you following this thread?) to
provide an easier way to distinguish SE from C++ exceptions, so I can
put in my code:

#ifdef _MSC_VER
catch (MSC::StructuredException &)
{
throw;
}
#endif

or even turn it off entirely by a command-line switch.

> > of course it threw an access violation - which was
> > promptly absorbed by the nearest "catch (...)" statement.
>
> A good example of why it is evil.

No, I'd say this is a good example of hijacking. To me, "catch (...)"
means "catch any C++ exceptions that my program throws" - because *that*
is what the standard *says* it should do.

> C++ exception-handling cannot correctly handle exceptions that cannot be
> caught by a C++-accessible name. If you need to handle non-C++
> platform-specific exceptions, then you must use a non-C++ platform-specific
> mechanism.

But I don't _want_ to catch them - my compiler is _forcing_ me to catch
them.

> > Are there any implementations besides MSVC that support structured
> > exceptions?
>
> Tru64 Unix, OpenVMS, Metrowerks.

Thanks. Of these implementations, do any of them allow you to catch the
exception by a specific type, or do you use (...) to catch them? In
other words, how difficult is it to differentiate between a C++
exception and a SE?

--
Jim

David Abrahams

unread,
Jul 17, 2002, 6:38:19 AM7/17/02
to

"Hillel Y. Sims" <use...@phatbasset.com> wrote in message
news:XBNY8.48163$6r.15...@news4.srv.hcvlny.cv.net...

>
> "Jim Hyslop" <jhy...@ieee.org> wrote in message
> news:MPG.17995092a...@news1.on.sympatico.ca...
> > No, catch(...) is about catching a C++ exception.
>
> std::exception is the path to nirvana (and robust code).
>
> 1) Never use catch(...), especially in portable code.

How would you write uninitialized_fill without catch(...)?

> 2) Always derive all custom exception-types from std::exception (or
> subclass), without exception.
> 3) Catch all C++ exceptions (where necessary) via catch (std::exception&),
> which is guaranteed to work if rule 2 is followed.

Yeah, but if you're interfacing with other peoples' libraries, or writing
templates, or writing frameworks that supply base classes with virtual
functions, you don't always have control over the types of exceptions that
get thrown. Writing certain kinds of exception-neutral code efficiently can
be extremely difficult without catch(...).

> catch (std::exception&) is all about catching all C++ exceptions. catch
> (...) is specifically about catching anything the platform might possibly
> throw at you (such as access violation) that lives on the same native
> runtime mechanism on which C++ exception-handling is implemented, without
> any knowledge of its context or type. I have read (hopefully carefully
> enough) the standard and found nothing which explicitly requires anything
> caught by catch(...) to be only something raised by a C++ "throw"
> statement.**

Well, that's true. On platforms which do something else, it's an extension.
It's an extension in the same sense that the standard gives libraries
permission to supply a zerovectors() function which sets the length of all
std::vectors in your program to zero. I don't think that's a reason to avoid
using std::vector, though it might be a good reason to avoid using
zerovectors().

> All this makes it legal for platforms (eg Windows, Tru64 Unix,
> OpenVMS) to implement their C++ runtime conveniently on top of the
> OS-native SEH exception mechanism, with the result that all SEH exceptions
> can be caught in catch(...) blocks. This makes it actually very
deceptively
> dangerous to use catch(...) as an attempt at achieving nothrow status
(such
> as in dtors)

It would almost never be a good idea to do that anyway, even in the absence
of some kind of "OS-native SEH exception mechanism".

> or for error protection, because that block is likely to be
> executed not just upon throw of a C++ exception, but also upon a fatal
> corruption of the program state (such as access violation) which is raised
> as an SEH exception.

The cure for that is "don't corrupt the program state". If it's fatal anyway
it doesn't matter (except from a debugging POV -- any system which takes
unwinding actions before I get to inspect the program state on a crash just
has poor QOI).

> This means it is unknowingly possible that it is
> already far too late for any attempt at nothrow or error protection.
(Error
> correction of that sort of error, if any, must happen explicitly via
> platform-specific API code, and should not be attempted by ordinary
generic
> user code.) Even in a nothrow block, capturing a non-C++ fatal process
> exception and continuing normal execution after that point as if nothing
bad
> actually happened is virtually always a Very Bad Thing

That's virtually always a Very Bad Thing even with a regular C++ exception.

> (especially if you
> try to write out some important data somewhere which is possibly
unknowingly
> corrupted...).
>
> There is a simple way to write correct nothrow code that does not suffer
> from this problem. _All_ C++ exceptions (including custom-defined types of
> even minimal complexity) must always be inherited from std::exception (or
> subclass).

This is misguided. If your nothrow functions are full of catch(xxx) {}
blocks which are designed to absorb all problems, you're doing something
wrong -- no matter whether you spell xxx "..." or "std::exception&". Nearly
every nothrow function is nothrow by virtue of inductive reasoning: it
doesn't call anything which can throw. The very few exceptions to this rule
can be thought of as "try to do yyyy if possible, but it doesn't really
matter whether it works".

> Non-std::exception-derived objects (such as int, or char*) should
> simply never be thrown.

Probably true, because the type is simply not descriptive enough.

> It is just a bad idea to throw any kind of exception
> object other than something derived from std::exception.

This kind of absolutism is bad for thinking programmers.

> The ultimate base
> class of any custom exception hierarchies should always inherit from
> std::exception. If you have a third-party library that uses exception
> objects that are not derived from std::exception which you cannot correct,
> then you're out of luck; you would need to additionally explicitly use
> "catch (library::base_exc&)" in all instances to catch those exceptions.
> Substitution of catch(...) is not a suitable strategy, as it opens the
door
> to receive non-C++ exceptions.

From the POV of the standard, there're no such things as "non-C++
exceptions", and many platforms don't have such a beast. Anyway, what do you
think the behavior should be if your program's running along happily and a
"non-C++ exception" passes through it?

> Always derive all exception objects from std::exception (or subclass),
> without exception. This is the only way to correctly catch all C++
> exceptions in one statement without interfering with OS-specific non-C++
> mechanisms.
>
> By following this simple and straightforward convention, it makes it
> possible in all cases to correctly catch _all_ (and ONLY) C++ exceptions
via
> one blanket statement (of course, even this is not necessarily completely
> safe all the time, but sometimes it is necessary...). C++ language code
> cannot and should not attempt to intervene in OS-native non-C++ exceptions
> under the vast majority of circumstances, and especially not inadvertent
> circumstances (even to try to do cleanup), as it has no inherent knowledge
> of OS-native implementation and context.

Well, what *should* happen? If your C++ program's not going to catch these
alien things, aren't they going to terminate your program anyway? In that
case, wouldn't it be better to install hooks which call dumpcore() or the
equivalent right where the things are getting thrown?

> Observance of the std::exception-or-bust rule provides an easy way to
avoid
> any need for or ill concerns resulting from use of catch(...).
>
> >MSVC allows [catch (...)] to
> > catch a hardware exception
>
> Exactly why we must all avoid it.

Not all of us need to be constrained by the brokenness of MSVC. They're
going to fix that eventually. In the meantime I'm willing to use my
_set_se_handler() hack and to trust that the very small quantity of code I
have in catch() blocks is not crashing in a way that I need to recover the
exact program state for debugging purposes.

> [..]
> > of course it threw an access violation - which was
> > promptly absorbed by the nearest "catch (...)" statement.
>
> A good example of why it is evil.

The evil here is a poor implementation choice which intertwined what should
have been a simple resumption model mechanism for handling OS traps with the
clean C++ exception implementation.

> C++ exception-handling cannot correctly handle exceptions that cannot be
> caught by a C++-accessible name. If you need to handle non-C++
> platform-specific exceptions, then you must use a non-C++
platform-specific
> mechanism. This can indeed make it (very much) more difficult to write
> robust C++ code for use on environments that do not fully integrate their
> native error-handling mechanisms with the C++ exception-handling
mechanism.

Au contraire, those environments are part of the problem. Full separation of
resumption-model for hardware faults and undefined behavior from termination
model for language-level exceptions is what's needed.

> However, as clearly displayed by your problem above, catch(...) is
certainly
> not the path to achieving robust high-availability code.

On that we are in agreement. However, catch(std::exception&) is no magic
bullet either.

> > Are there any implementations besides MSVC that support structured
> > exceptions?
>
> Tru64 Unix, OpenVMS, Metrowerks.

The first 2 are platforms; the third is a collection of implementations of
which only one supports SEH to my knowledge.

> **Even if that statement is not 100% correct, or in some cases you can
> completely disable SEH/C++ interaction via non-portable #pragma or
> compile-flag, I can imagine a situation involving a special
platform-native
> private C++ exception type, _not_ inherited from std::exception, that is
> inaccessible to user code and only the OS can catch it by name (eg, to
> represent a fatal process error for an OS written with C++). User code
would
> only be able to interact with this special exception via catch(...),
subject
> to all the same problems described above.

It's possible to imagine all kinds of legal language/library extensions
which, if used, would undermine the robustness of any given language
feature. Trying to pick which language features to use based on ways we can
imagine them being undermined is a dangerous kind of FUD for anyone with a
creative mind.

-Dave

Alexander Terekhov

unread,
Jul 18, 2002, 10:40:19 AM7/18/02
to

Francis Glassborow wrote:
>
> In article <3D326BB4...@web.de>, Alexander Terekhov
> <tere...@web.de> writes
> >
> >Do you see the point? Or am I missing and/or misunderstanding
> >something?
>
> Yes, you have been twice asked what 'khm' stands for. The first time you
> gave a link that does not appear to answer the question and this time
> you have provide two screen fulls that still does not appear to answer
> the question.

Okay, I'll try one more time (see some comp.std.c++ archive for the full
context -- Subject: Re: throw() can be good for optimization):


Francis Glassborow wrote:
[...]
> An empty throw spec. is just an ES and is treated the same way as all
> others (we try to avoid special casing things). While it is true that
> the unexpected_handler cannot do anything to allow the process to
> continue because it cannot replace the exception with another, in
> general (other than for empty throw specs) this is possible and the
> rules (reasonably IMO) state that such a catch is effectively handling
> the original exception.

What "such catch"? I am talking about stack-unwinding
PRIOR to unexpected()/terminate() invocation and "problems"
(as it seems to me) resulting due to this behavior, for
example:

<snip the link to "khm" example>

> The design may not be ideal but to describe it as emphatically seriously
> broken is a serious over-statement.

Yeah, e.g. if/when you just can't debug/analyze problems
(abends) once you ship your programs to customer (without
full recreation data/..., if its possible/deterministic
at all/enough), that's just "may not be ideal", and of
course, "broken is a serious over-statement", right! ;-)

regards,
alexander.

Alexander Terekhov

unread,
Jul 18, 2002, 10:43:09 AM7/18/02
to

"Hillel Y. Sims" wrote:
>
> "Jim Hyslop" <jhy...@ieee.org> wrote in message
> news:MPG.17995092a...@news1.on.sympatico.ca...
> > No, catch(...) is about catching a C++ exception.
>
> std::exception is the path to nirvana (and robust code).

No.

> 1) Never use catch(...), especially in portable code.
> 2) Always derive all custom exception-types from std::exception (or
> subclass), without exception.
> 3) Catch all C++ exceptions (where necessary) via catch (std::exception&),
> which is guaranteed to work if rule 2 is followed.

Hillel, I'm sorry for being a bit sort-of too-"persistent",
but I'm still awaiting your reply to the following comp.std.c++
article of mine:

http://groups.google.com/groups?selm=3C7DEFBB.C48B0694%40web.de
< uhmm, id: 3-C-7-D-E-F-B-B-.-C-4-8-B-0-6-9-4-%-4-0-w-e-b-.-d-e >

"Hillel Y. Sims" wrote:
[...]
> Few people seem to be aware of this issue (or at least discuss it much
> publicly), but many of us program in a multi-threaded world. For example,
> following the typical exception-safety conventions recommended by
> Meyers/Sutter/etc. for protecting nothrow code via try {...} catch (...) {}
> as necessary is not completely valid when thread-cancellation exceptions are
> used; it is inappropriate to catch and swallow a thread-cancellation
> exception. Thread-cancellation must be disabled in these regions in order
> for the catch (...) {} to be correct. (Actually, it should probably even be
> catch (std::exception&) {} because you don't really want to catch any
> unknown exceptions such as accvio...)

You don't really want to catch&ignore any of these:

logic_error
domain_error
invalid_argument
length_error
out_of_range
runtime_error
range_error
overflow_error
underflow_error

*known* exceptions TOO (and anything else) IF they
were thrown *UNEXPECTEDLY*. Gee! Why not just terminate
the whole process, leaving that nice dump-info for the
friendly service/change team and try to recover/retry
in a NEW/CLEAN address space from the persistent (non-/
less-volatile storage) program-state info saved (e.g.
incrementally updateable objects store, home grown) at
the last GOOD (as it appeared and most likely *truly*
good) CHECK POINT!? Just consider/treat it as the
unexpected power-off/loss situation. "Good" programs
SHOULD deal with this too, IMHO! ;-)

> This makes it difficult to write
> portable code, since it cannot be correct without CancelGuard on
> multi-threaded systems. It would definitely be nice if the whole issue could
> be more smoothly integrated into the language

Yup. Something along the lines of:

- async-cancel-safety enforced by the compiler;
- bool expected_exception<T>();
- bool unwinding(T*);
- something to code LOCAL context templates/objects
that would have the same local access/visibility
as Java's "finally" clauses do;
- thread-safe static locals for IMMUTABLE lazy
singeltons;
- transition of <pthread.h> into <cthread>;
- some decent <thread> C++ "wrappers" that would
basically do the same as <cthread> stuff, BUT
in MORE EXPRESSIVE/LESS ERROR-PRONE (get rid
of "detach", etc) way then the current C-style
threaded programming.

...and, of course, post-/pre- c/d-tors! ;-)

regards,
alexander.

Andrea Griffini

unread,
Jul 18, 2002, 10:58:47 AM7/18/02
to
On 17 Jul 2002 06:33:26 -0400, jhy...@ieee.org (Jim Hyslop) wrote:

>No, I'd say this is a good example of hijacking. To me, "catch (...)"
>means "catch any C++ exceptions that my program throws" - because *that*
>is what the standard *says* it should do.

I stepped today on that VC++ problem too. Code written by a
collegue was behaving very strangely. It turned out he used
catch(...) adsorbing the exception in a DLL. The exception are
used inside the DLL but catch(...) intercepted also memory
faults hiding errors in a strange way.

After some thinking I've come to the conclusion that catch(...)
is good only if you are going to terminate the program (may be
after some last desperate tentative to save something - but I'm
not sure if I like that) as adsorbing an unknown event doesn't
describe what I call a robust program... it's just code that
*hide* errors and that cripple my documents instead of dying
immediately as it should. To not make me waste last hour on
my WP doc it make me waste last *month* crippling its internal
structure with a bad save that I'll discover only after a
long time (just after all backups got a corrupted version,
Murphy says).

I think however that MS is not violating anything doing that...
writing out of an array is Undefined Behaviour and performing
a stack unwinding until it gets to a catch(...) is something
that may happen once you enter the dark territories of UB.

So using catch(...) to adsorb an exception is in my opinion a
"don't", but I think MS did a good thing with current behaviour
instead of formatting my hard disk (UB may mean that too).

If your program got to a catch(...) and that is not because
of one of your throws then you already violated the rules,
so I wouldn't complain ... you were anyway just going to
kill your program immediately with a loud yell, right ?


Andrea

Alexander Terekhov

unread,
Jul 18, 2002, 11:35:21 AM7/18/02
to

David Abrahams wrote:
[...]

> How would you write uninitialized_fill without catch(...)?

Show me the code, please.

[...]


> Yeah, but if you're interfacing with other peoples' libraries, or writing
> templates, or writing frameworks that supply base classes with virtual
> functions, you don't always have control over the types of exceptions that
> get thrown. Writing certain kinds of exception-neutral code efficiently can
> be extremely difficult without catch(...).

Examples?

[...]


> The cure for that is "don't corrupt the program state". If it's fatal anyway
> it doesn't matter (except from a debugging POV

No, not only "except from a debugging POV".

> -- any system which takes
> unwinding actions before I get to inspect the program state on a crash just
> has poor QOI).

Okay, but what is this, then:

"The fields unexpectedHandler and terminateHandler contain
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pointers to the unexpected and terminate handlers at the
point where the exception is thrown.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ISO C++....(18.6.2.4) states that the handlers to be
used are those active immediately after evaluating the
throw argument. If destructors....not used
until unwinding is complete."
^^^^^^^^^^^^^^^^^^^^^^^^^^^

To me, that's nothing but poor SOMETHING in the current
C++ standard. Please-please, fix it, please.

[...]


> From the POV of the standard, there're no such things as "non-C++
> exceptions", and many platforms don't have such a beast. Anyway, what do you
> think the behavior should be if your program's running along happily and a
> "non-C++ exception" passes through it?

Consider [somewhere in the "threads/C/C++ related" DEC->Compaq->HP docu]:

"You can use the C language exception handling mechanism (SEH) to catch
exceptions. You can catch exceptions in C++ using catch(...), and propagation
of exceptions will run C++ object destructors. Currently, C++ code cannot
catch specific exceptions. .... ^^^^^^^^^
(These restrictions will be reduced or removed in a future release.)"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

> It's possible to imagine all kinds of legal language/library extensions
> which, if used, would undermine the robustness of any given language
> feature.

The robustness of the standard C++ exceptions "feature" is /already/
and _/totally/_ undermined by a) implementation-defined unwinding for
uncaught exceptions [debugging is a /secondary/ issue here, really]
and b) *required unwinding* on violations of ex. specs; IOW, NOT by
something like SEH extensions, IMO.

regards,
alexander.

Alexander Terekhov

unread,
Jul 18, 2002, 11:35:57 AM7/18/02
to

Matthew Collett wrote:
[...]

> Not if your RAII is doing its job. Unwinding the stack as you leave
> c() will call the RAII object's destructor, which should reset the
> unexpected handler to whatever it was before entering c(). The
> implicit catch(...) in a() that actually _calls_ the unexpected
> handler isn't reached until after this resetting has occurred, so
> all should be well.
>
> > Or am I missing and/or misunderstanding something?
>
> Or maybe I am ...

Somewhat vague standard-bits aside [you might want to check out
the posts from Mr. Lancaster (in the comp.std.c++ thread I've
referenced earlier) attempting to interpret it... and I agree
with his interpretation], consider:

http://www.codesourcery.com/cxx-abi/abi-eh.html

"....
2.1 C++ Exception Objects

A complete C++ exception object consists of a header,
which is a wrapper around an unwind object header with
additional C++ specific information, followed by the
thrown C++ exception object itself. The structure of
the header is as follows:

struct __cxa_exception {
std::type_info * exceptionType;
void (*exceptionDestructor) (void *);
unexpected_handler unexpectedHandler;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
terminate_handler terminateHandler;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
....


The fields unexpectedHandler and terminateHandler contain

pointers to the unexpected and terminate handlers at the

point where the exception is thrown. The ISO C++ Final
Draft International Standard [lib.unexpected] (18.6.2.4)


states that the handlers to be used are those active
immediately after evaluating the throw argument. If

destructors change the active handlers during unwinding,
the new values are not used until unwinding is complete."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

regards,
alexander.

Doug Harrison

unread,
Jul 18, 2002, 2:57:12 PM7/18/02
to
Hillel Y. Sims wrote:

>catch (std::exception&) is all about catching all C++ exceptions. catch
>(...) is specifically about catching anything the platform might possibly
>throw at you (such as access violation) that lives on the same native
>runtime mechanism on which C++ exception-handling is implemented, without
>any knowledge of its context or type.

People often think that's a good idea. Here are some sample messages
explaining why I completely disagree with them:

http://groups.google.com/groups?selm=eW%23ZKH8P%23GA...@uppssnewspub05.moswest.msn.net
http://groups.google.com/groups?selm=k9etqs855giltd5se...@4ax.com

FWIW, I've been arguing this point for eight years, and I've never
heard a reasonable argument why catch(...) should catch untranslated
Win32 structured exceptions.

--
Doug Harrison
d...@mvps.org

Hillel Y. Sims

unread,
Jul 19, 2002, 8:36:17 AM7/19/02
to

"Doug Harrison" <d...@mvps.org> wrote in message
news:lihcjus48p7c5vvle...@4ax.com...

> Hillel Y. Sims wrote:
>
> >catch (std::exception&) is all about catching all C++ exceptions. catch
> >(...) is specifically about catching anything the platform might possibly
> >throw at you (such as access violation) that lives on the same native
> >runtime mechanism on which C++ exception-handling is implemented, without
> >any knowledge of its context or type.
>
> People often think that's a good idea. Here are some sample messages
> explaining why I completely disagree with them:
>
>
http://groups.google.com/groups?selm=eW%23ZKH8P%23GA...@uppssnewspub05.mosw
est.msn.net
>
http://groups.google.com/groups?selm=k9etqs855giltd5seolk6pv8ssnj2k7p6l@4ax.

com
>
> FWIW, I've been arguing this point for eight years, and I've never
> heard a reasonable argument why catch(...) should catch untranslated
> Win32 structured exceptions.
>

I totally agree with you in principle. _However_, from a realistic/pragmatic
point of view, this behavior exists and is the default behavior on many
platforms, and is frankly unlikely to change anytime in the near future (and
it is NOT just Windows, it's also an issue on Tru64 and OpenVMS and possibly
others, which interests me personally since I do most of my development on
VMS). AND in fact, there is NO workaround for it on VMS (maybe on Windows
you have a workaround; even if it is fully reliable, I wonder about the
relative merits of a platform-specific workaround vs. the always-correct
fully-portable alternative of std::exception-derived exceptions)

If every bit of your code ONLY throws and catch exceptions inherited from
std::exception, then by inductive reasoning you never need to worry about
catch(...) (even from generic templated code) and you never need to worry
about intercepting OS exceptions regardless of the platform. I won't go
quite so far as to say it's a mistake in C++ that you can throw exceptions
other than inherited from std::exception, but I will strongly suggest it is
very poor form for programmers to do so (and I do note that all std library
exceptions inherit from std::exception). Please, anyone, show me one aspect,
minor or major, whereby there is any downside to inheriting all your
exception objects from std::exception (other than having to type a few extra
characters to define the object..)?

As far as other aspects of catch(...), let me just try to make a couple of
points that will hopefully cover all the issues:

1) The "catch(...) { throw; }" rethrow idiom -- IF you _always_ _rethrow_
the UNALTERED exception from a catch(...) block (and it is fairly
unconscionable to swallow it / "translate" it... so far Jim Hyslop and
Andrea Griffini have posted examples of the evil that happens when you
swallow unknown exceptions; and you can't legitimately try to translate it
either -- how can you even try to translate something that you can't even
possibly know what it is???) -- if you rethrow the exception, this is not AS
bad as swallowing it. However, there are _still_ two undesirable side
effects from result even this seemingly harmless _forced_ unwinding:
- high importance: if you are unwinding during a hardware exception, you
may end up corrupting persistent extra-process state (eg. disk files,
network, etc). Since the fact that a hardware exception has been raised
indicates that there is unknown corruption in your program state, any
unwinding at all in this state is usually a bad idea. Much better to rely on
automatic object (have you tried Alexandrescu/Marginen's ScopeGuard package?
ON_BLOCK_EXIT is a safe 99%-"finally" for C++! It's fabulous!!) /
std::exception-only unwinding, in which case you can usually avoid forced
unwinding due to a fatal program state corruption problem (assuming your
platform doesn't force it on you, but that's clearly an aspect of QoI; at
least VMS doesn't force it unless there is catch(...)). (and yes, you can
also avoid this problem by not corrupting your program state in the first
place, ha ha..)

This is one objection to even using the "catch(...) { throw; }" form -
it can cause unintended permanent data corruption.

- moderate importance: it can interfere with post-crash debugging. At
least on VMS, the stack traceback / core dump mechanism which is triggered
when an exception causes a program to terminate can only snapshot the
deepest level of the call stack which is still available when the exception
propagates outside of main(). If a catch(...) is encountered along the way,
the entire portion of the call stack deeper than that is unwound and cleaned
up before the exception is rethrown, and important debugging context is
permanently lost. When the exception finally propagates outside main() and
causes the abnormal termination / stack trace / core dump, the call stack no
longer shows any meaningful information past the last catch(...) block which
was encountered.

Well I'm sure that some people may think "QoI!" about this point. But
please consider again that this is the reality behind some OSs, and the
ability to avoid catch(...) completely through use of std::exception-derived
exceptions removes this entire issue from the table without having to worry
about if/when a vendor is going to fix their OS or if there are
platform-specific hooks to trap fatal errors and in the meantime we're stuck
scratching our heads wondering why std::vector constructor's catch(...)
block shows up as the last thing on the call stack and what could have
possibly actually triggered the exception in the user-defined type?


2) The "catch(...) {}" form -- often propounded (NOT by me, thank you) as a
way to make destructors nothrow safe. Of course you typically determine
nothrow status by inductive reasoning, and typically you do _not_ wrap your
destructors in try { ... } catch (xxx) {} blocks of any nature (_I_ am _not_
suggesting this as general good practice), _however_ please consider a
destructor in a high-reliability fault-tolerant application which must call
a cleanup function in an external DLL. You, as the programmer of this object
, may be legitimately concerned that that function could throw an exception,
and that would be a Bad Thing to allow to propagate outside your destructor.
Thus, the advice commonly encountered in various print media by major
authors and other outlets would be to do something like the following:
Obj::~Obj()
{
try {
dll_cleanup_function_that_does_zeus_knows_what();
}
catch (...) {}
}

Can we all agree that this is Very Bad in the presence of hardware
exceptions that may come through the catch(...)? (I am not claiming that
those who have suggested that idiom were somehow "dumb" or did not know what
they were talking about -- rather this seems to be a somewhat under-explored
area and is not even an issue at all on most unix boxes which many people
are familiar with, so I can understand why this advice may have been given
in seemingly good conscience in the past, but I do feel it is somewhat
misguided in light of the hardware exception issue.)

Now, if your application-level exception objects are being thrown
willy-nilly inherited from any random hierarchy or even ints and char*s, or
you are writing templated code, then you probably sort of feel like you have
no choice, because the alternative is that your application may terminate
randomly due to unhandled exception. Well let me just say that if this is
the case, the catch (...) {} form is NOT safely portable and is absolutely
no safer, and will at most give a false sense of security, because now your
application may randomly NOT terminate when it really should have (and now
your elevator software that should have triggered an automatic system reboot
upon fatal exception will continue to run with a faulty program state and
maybe decide to just accelerate downward at maximum speed from the top floor
with a full load of passengers...).

The only really safe and portable alternative is to rely on the inductive
reasoning available whereby all application exceptions are inherited from
std::exception. If this is the case, then it is both legal and safe and
fully robust to use "catch (std::exception&) {}" as the maximum-strength
"cannot let any exceptions propagate" form of exception handling, and you
can allow hardware faults / OS exceptions to propagate and be handled by
their own appropriate mechanism (for which I think we all agree at this
point that C++ catch is not appropriate).


To sum up, I agree in principle with those who believe in total separation
of hardware and software exceptions. However, from a pragmatic viewpoint,
the separation is not complete and is not something that can easily be
escaped, but it can be easily achieved by only using exceptions that are
inherited from std::exception. This provides the logical basis for being
able to effectively do a catch-all-C++-exceptions when necessary without
having to worry about the negative side-effects of catch(...).

I suggest that using/throwing any exceptions not inherited from
std::exception is at best very poor/lazy form in almost all cases, except
maybe some very special/rare circumstances where you would have to have a
very good reason for doing so (so as to avoid corrupting the whole logical
basis of the catch(std::exception&) as catch-all-C++-exceptions). I suggest
it is virtually always inappropriate to use catch(...), substituting
catch(std::exception&) instead in those circumstances when it is absolutely
necessary. (Maybe this would even encourage more people to inherit their
exceptions from std::exception since they will see that ... will not "save"
them.)

Any programmer who wishes to use C++ exceptions really should have a good
understanding of this interaction, that exists and is probably not going
away anytime soon, and how to safely work with it, or they will actually end
up with less-robust software than they would have had had they continued to
use the old non-exception style of programming. If you are on various unix
boxen, then you apparently don't even need to consider this issue at all,
and if you're on Windows, then you apparently have a platform-specific
workaround available, so good luck with that (assuming it is 100% reliable),
but PLEASE consider that there are not always reliable platform-specific
workarounds and that the simple act of always inheriting your exceptions
from std::exception does provide a fully-portable and completely robust
basis for automatic and absolute separation of all hardware/software
exception interaction concerns.

thanks,
hys

--
Hillel Y. Sims
FactSet Research Systems
hsims AT factset.com

Alan Griffiths

unread,
Jul 20, 2002, 6:25:29 AM7/20/02
to
agr...@tin.it (Andrea Griffini) wrote in message news:<3d35ab3...@news.tin.it>...

> On 17 Jul 2002 06:33:26 -0400, jhy...@ieee.org (Jim Hyslop) wrote:
>
> >No, I'd say this is a good example of hijacking. To me, "catch (...)"
> >means "catch any C++ exceptions that my program throws" - because *that*
> >is what the standard *says* it should do.
>
> I stepped today on that VC++ problem too. Code written by a
> collegue was behaving very strangely. It turned out he used
> catch(...) adsorbing the exception in a DLL. The exception are
> used inside the DLL but catch(...) intercepted also memory
> faults hiding errors in a strange way.

It has been a while since I used VC++ (and things may have changed),
but I remember catch (...) sometimes trapped normal OS SEHs that would
otherwise be "resumed" without the application being aware that
anything had happened. Having unwound the stack this meant that there
was no way to recover.

> After some thinking I've come to the conclusion that catch(...)
> is good only if you are going to terminate the program

No, if things are so bad that you are going to terminate the program
do just that! Don't mess about unwinding the stack.

Anyway, there is a definite (although occasional) need for such
constructs as:

try {
. . .
}
catch (...) {
. . .
throw;
}

> (may be
> after some last desperate tentative to save something - but I'm
> not sure if I like that) as adsorbing an unknown event doesn't
> describe what I call a robust program... it's just code that
> *hide* errors and that cripple my documents instead of dying
> immediately as it should.

I agree that errors shouldn't be hidden.

> To not make me waste last hour on
> my WP doc it make me waste last *month* crippling its internal
> structure with a bad save that I'll discover only after a
> long time (just after all backups got a corrupted version,
> Murphy says).
>
> I think however that MS is not violating anything doing that...
> writing out of an array is Undefined Behaviour and performing
> a stack unwinding until it gets to a catch(...) is something
> that may happen once you enter the dark territories of UB.

This is a "quality of implementation" issue: the bad choice that MS
has made that causing "unknown events" to be hidden by code that is
perfectly reasonable C++.

> So using catch(...) to adsorb an exception is in my opinion a
> "don't",

And so is using catch (const my_exception&) to adsorb an exception.

> but I think MS did a good thing with current behaviour
> instead of formatting my hard disk (UB may mean that too).

I don't think I'd feel grateful that someone blew my arm off (instead
of blowing my head off). You clearly think differently.

> If your program got to a catch(...) and that is not because
> of one of your throws then you already violated the rules,
> so I wouldn't complain ... you were anyway just going to
> kill your program immediately with a loud yell, right ?

But if I don't own all of the code in the program (eg because I'm a
library author) then I may not have any control of the range of [C++]
exceptions that propagate.
--
Alan Griffiths <al...@octopull.demon.co.uk> ACCU Chairman
<ch...@accu.org>
http://www.octopull.demon.co.uk/ http://accu.org/

Alexander Terekhov

unread,
Jul 23, 2002, 4:28:05 PM7/23/02
to

Doug Harrison wrote:
>
> Hillel Y. Sims wrote:
>
> >catch (std::exception&) is all about catching all C++ exceptions. catch
> >(...) is specifically about catching anything the platform might possibly
> >throw at you (such as access violation) that lives on the same native
> >runtime mechanism on which C++ exception-handling is implemented, without
> >any knowledge of its context or type.
>
> People often think that's a good idea. Here are some sample messages
> explaining why I completely disagree with them:
>
> http://groups.google.com/groups?selm=eW%23ZKH8P%23GA...@uppssnewspub05.moswest.msn.net
> http://groups.google.com/groups?selm=k9etqs855giltd5se...@4ax.com

: Now, suppose you had the following sequence:
:
: // Begin C++ exception-free code.
: ... // Causes an access violation due to a bug.
: // End C++ exception-free code.

And now, suppose you had the following sequence:

// Begin C++ code.
... // Causes an UNEXPECTED {std::}whatever {logic_error/
// domain_error/invalid_argument/length_error/out_of_range/
// runtime_error/range_error/overflow_error/underflow_error/
// etc. *usually* >>UNEXPECTED<< stuff...
//
// >>due to a bug<<.
//
// End C++ code.

> FWIW, I've been arguing this point for eight years, and I've never
> heard a reasonable argument why catch(...) should catch untranslated
> Win32 structured exceptions.

It should. And that's non-issue [implementation-defined unwinding and
"similar" problems {IMO} with C++ ex.specs. aside] if you catch *ONLY*
things you KNOW/REALLY want/need, AFAICS.

regards,
alexander.

Francis Glassborow

unread,
Jul 23, 2002, 4:29:25 PM7/23/02
to
In article <3D3547F2...@web.de>, Alexander Terekhov
<tere...@web.de> writes
>
>Francis Glassborow wrote:
> >
> > In article <3D326BB4...@web.de>, Alexander Terekhov
> > <tere...@web.de> writes
> > >
> > >Do you see the point? Or am I missing and/or misunderstanding
> > >something?
> >
> > Yes, you have been twice asked what 'khm' stands for. The first time you
> > gave a link that does not appear to answer the question and this time
> > you have provide two screen fulls that still does not appear to answer
> > the question.
>
>Okay, I'll try one more time (see some comp.std.c++ archive for the full
>context -- Subject: Re: throw() can be good for optimization):

OK, clearly we must try guessing what khm stands for, my offer is:

Knowledge Helps Mentation.

Any others?


>
>
>Francis Glassborow wrote:
>[...]
> > An empty throw spec. is just an ES and is treated the same way as all
> > others (we try to avoid special casing things). While it is true that
> > the unexpected_handler cannot do anything to allow the process to
> > continue because it cannot replace the exception with another, in
> > general (other than for empty throw specs) this is possible and the
> > rules (reasonably IMO) state that such a catch is effectively handling
> > the original exception.
>
>What "such catch"? I am talking about stack-unwinding
>PRIOR to unexpected()/terminate() invocation and "problems"
>(as it seems to me) resulting due to this behavior, for
>example:

If a programmer elects to use and empty throw specification one of the
consequences is the behaviour you describe. If you do not want this
behaviour you will have to write your code differently. The point is
that the unexpected_handler is deemed by the language to have handled
the exception and so the stack will be unwound. This is necessary to
allow the handler to do something reasonable and throw another
exception. Of course in the case of an empty throw spec there is no
other type that can be used but empty throw specs are used in exactly
those cases where the programmer is certain that exceptions cannot reach
this point.


--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Ken Hagan

unread,
Jul 23, 2002, 7:12:02 PM7/23/02
to
"Alan Griffiths" <al...@octopull.demon.co.uk> wrote ...

>
> It has been a while since I used VC++ (and things may have changed),
> but I remember catch (...) sometimes trapped normal OS SEHs that would
> otherwise be "resumed" without the application being aware that
> anything had happened. Having unwound the stack this meant that there
> was no way to recover.

[off topic, at least for clc++m, but this is presented as a killer VC design
bug
sufficiently often that non-MSVC users might appreciate the clarification]

Unless you use signals, this isn't true.

The OS emits structured exceptions for some events that the CRT expects to
handle using signals, like SIGSEGV, SIGILL and SIGFPE. If you have
registered a handler for these, then it is called by an SEH block that wraps
your "main()" function. If you use catch(...) then you stop the search for
an
SEH handler from reaching this point. (So-called "vectored" SEH handlers
would presumably allow MS to move this translation code out of the call
stack, but they aren't supported prior to Win2K.)

However, there is so little that can be portably done with signals that most
people never use them, so they are never bothered by this. Furthermore,
Win32 GUI programs and COM servers already have the SEH equivalent
of catch(...) inserted by the operating system around window procedures
and server stubs (respectively) so anything MS wrap around main() is a
total irrelevance. In any case, the whole environment is such a mish-mash
of code from different compilers and run-times that I would classify the
whole
lot as a non-hosted implementation, and then most bets are off anyway.

(It is sometimes alleged that stack guard pages are obstructed by catch(...)
but this is an urban myth, since those faults are not passed on to user
space.)

David Abrahams

unread,
Jul 23, 2002, 7:46:31 PM7/23/02
to

"Hillel Y. Sims" <use...@phatbasset.com> wrote in message
news:beMZ8.87143$6r.29...@news4.srv.hcvlny.cv.net...

> If every bit of your code ONLY throws and catch exceptions inherited from
> std::exception, then by inductive reasoning you never need to worry about
> catch(...) (even from generic templated code) and you never need to worry
> about intercepting OS exceptions regardless of the platform.

Incorrect. Somebody else's code might throw something else at me, even if
every bit of my code throws and catches std::exception-derived classes (it
does, BTW, because... well, why shouldn't it?)

> I won't go
> quite so far as to say it's a mistake in C++ that you can throw exceptions
> other than inherited from std::exception, but I will strongly suggest it
is
> very poor form for programmers to do so (and I do note that all std
library
> exceptions inherit from std::exception). Please, anyone, show me one
aspect,
> minor or major, whereby there is any downside to inheriting all your
> exception objects from std::exception (other than having to type a few
extra
> characters to define the object..)?

They all get a virtual table. That could be an issue for some
resource-constrained environments. The exception-specification on the what()
method might cause code pessimization on some platforms.

> As far as other aspects of catch(...), let me just try to make a couple of
> points that will hopefully cover all the issues:
>
> 1) The "catch(...) { throw; }" rethrow idiom -- IF you _always_ _rethrow_
> the UNALTERED exception from a catch(...) block (and it is fairly
> unconscionable to swallow it / "translate" it... so far Jim Hyslop and
> Andrea Griffini have posted examples of the evil that happens when you
> swallow unknown exceptions; and you can't legitimately try to translate it
> either -- how can you even try to translate something that you can't even
> possibly know what it is???)

Red herring. You don't know what a std::exception is either -- it could be
any derived class.

> -- if you rethrow the exception, this is not AS
> bad as swallowing it. However, there are _still_ two undesirable side
> effects from result even this seemingly harmless _forced_ unwinding:
> - high importance: if you are unwinding during a hardware exception,
you
> may end up corrupting persistent extra-process state (eg. disk files,
> network, etc). Since the fact that a hardware exception has been raised
> indicates that there is unknown corruption in your program state, any
> unwinding at all in this state is usually a bad idea. Much better to rely
on
> automatic object (have you tried Alexandrescu/Marginen's ScopeGuard
package?
> ON_BLOCK_EXIT is a safe 99%-"finally" for C++! It's fabulous!!) /

Why do you think the code in a catch(...) block is any more prone to corrupt
than the code in a destructor is?

> std::exception-only unwinding, in which case you can usually avoid forced
> unwinding due to a fatal program state corruption problem (assuming your
> platform doesn't force it on you, but that's clearly an aspect of QoI; at
> least VMS doesn't force it unless there is catch(...)). (and yes, you can
> also avoid this problem by not corrupting your program state in the first
> place, ha ha..)

So what happens instead? Your program crashes anyway?

> This is one objection to even using the "catch(...) { throw; }"
form -
> it can cause unintended permanent data corruption.

I don't see how it's special in that regard.

> - moderate importance: it can interfere with post-crash debugging.

This one I understand.

> At
> least on VMS, the stack traceback / core dump mechanism which is triggered
> when an exception causes a program to terminate can only snapshot the
> deepest level of the call stack which is still available when the
exception
> propagates outside of main(). If a catch(...) is encountered along the
way,
> the entire portion of the call stack deeper than that is unwound and
cleaned
> up before the exception is rethrown, and important debugging context is
> permanently lost. When the exception finally propagates outside main() and
> causes the abnormal termination / stack trace / core dump, the call stack
no
> longer shows any meaningful information past the last catch(...) block
which
> was encountered.

Yep, that's bad stuff. Isn't there a way to hook the low-level crash handler
on VMS so it just dumps core immediately?

> Well I'm sure that some people may think "QoI!" about this point. But
> please consider again that this is the reality behind some OSs,

Reality is important.

> and the
> ability to avoid catch(...) completely through use of
std::exception-derived
> exceptions

That's a false premise for a library writer, unless I want to impose that
requirement on my users (and I don't).

> removes this entire issue from the table without having to worry
> about if/when a vendor is going to fix their OS or if there are
> platform-specific hooks to trap fatal errors and in the meantime we're
stuck
> scratching our heads wondering why std::vector constructor's catch(...)
> block shows up as the last thing on the call stack and what could have
> possibly actually triggered the exception in the user-defined type?


Uh, yeah, now that you mention it: on the reality side, my standard library
implementation is likely to use catch(...) anyway.


> You, as the programmer of this object

> may be legitimately concerned that that function could throw an exception,
> and that would be a Bad Thing to allow to propagate outside your
destructor.
> Thus, the advice commonly encountered in various print media by major
> authors and other outlets would be to do something like the following:
> Obj::~Obj()
> {
> try {
> dll_cleanup_function_that_does_zeus_knows_what();
> }
> catch (...) {}
> }
>
> Can we all agree that this is Very Bad in the presence of hardware
> exceptions that may come through the catch(...)?

I'm not sure. Wasn't the program doomed to crash anyway? If hardware
exceptions are catchable, I'd write:

try {
dll_cleanup_function_that_does_zeus_knows_what();
}
catch(hardware_exception const&) { throw; }
catch (...) {}

If not, I hope that someone other than Zeus (i.e. documentation) can tell me
what exceptions the function can throw, so:

try {
dll_cleanup_function_that_does_zeus_knows_what();
}
catch(those_exceptions const&) {}

should be OK.

> (I am not claiming that
> those who have suggested that idiom were somehow "dumb" or did not know
what
> they were talking about -- rather this seems to be a somewhat
under-explored
> area and is not even an issue at all on most unix boxes which many people
> are familiar with, so I can understand why this advice may have been given
> in seemingly good conscience in the past, but I do feel it is somewhat
> misguided in light of the hardware exception issue.)

Well, I think I've explored the issue pretty thoroughly since I have to
support Windows.

<snip>

> The only really safe and portable alternative is to rely on the inductive
> reasoning available whereby all application exceptions are inherited from
> std::exception.

That's not really the only way. It's a simple way, but you can have as many
exception hierarchies as you want as long as you know all the root classes.

> Any programmer who wishes to use C++ exceptions really should have a good
> understanding of this interaction, that exists and is probably not going
> away anytime soon, and how to safely work with it, or they will actually
end
> up with less-robust software than they would have had had they continued
to
> use the old non-exception style of programming. If you are on various unix
> boxen, then you apparently don't even need to consider this issue at all,
> and if you're on Windows, then you apparently have a platform-specific
> workaround available, so good luck with that (assuming it is 100%
reliable),

It's not (I detailed the way in which it fails in my previous post). But
it's good enough for many purposes.

> but PLEASE consider that there are not always reliable platform-specific
> workarounds and that the simple act of always inheriting your exceptions
> from std::exception does provide a fully-portable and completely robust
> basis for automatic and absolute separation of all hardware/software
> exception interaction concerns.

assuming you have control over every exception that gets thrown.

Note that 17.4.4.8/3 gives your standard library implementation license to
throw exceptions not derived from std::exception:

"Any other functions
defined in the C++ Standard Library that do not have an
exception-specification may throw
implementation-defined exceptions unless otherwise specified."

-Dave

Doug Harrison

unread,
Jul 24, 2002, 11:45:29 AM7/24/02
to
Alexander Terekhov wrote:

That's a different scenario. In my C++ exception-free code sequence, I
can use all of C++ that doesn't throw exceptions. For example, I can
push_back() into a vector<int> whose capacity() > size(). I can use
the C subset, so I can use all the C Standard Library, all of the
Win32 API, call COM methods, etc. I discussed this in this recent
thread:

http://groups.google.com/groups?threadm=1h1v8u82mhr3iidgd1aeb11sekq80bapev%404ax.com&rnum=1&prev=/groups%3Fq%3Dg:thl1800401586d%
26dq%3D%26hl%3Den%26lr%3Dlang_en%26ie%3DUTF-8%26safe%3Doff%26selm%3D1h1v8u82mhr3iidgd1aeb11sekq80bapev%25404ax.com

In my example, the OS will normally handle an access violation by
displaying an error box, which tells me about the error and allows me
to debug the program or terminate it. An outer catch(...) subverts
this process, and a normally program-terminating bug causes my program
to unwind the stack on its way to my C++ exception recovery code. Upon
executing the bug, the program enters an unknown state, but it's
allowed to continue, as if a C++ exception I designed for had been
thrown.

In your example, you threw a C++ exception when you shouldn't have,
and it could be caught by a std::exception handler, not just
catch(...). There's no expectation of different behavior here. C++
exception handlers are supposed to catch C++ exceptions! So while you
may have a bug, I don't believe you have any reason to complain.

>> FWIW, I've been arguing this point for eight years, and I've never
>> heard a reasonable argument why catch(...) should catch untranslated
>> Win32 structured exceptions.
>
>It should. And that's non-issue [implementation-defined unwinding and
>"similar" problems {IMO} with C++ ex.specs. aside] if you catch *ONLY*
>things you KNOW/REALLY want/need, AFAICS.

Well, no. The point is that catch(...) catches non-C++ exceptions,
which destroys its usefulness for catching C++ exceptions.

Alexander Terekhov

unread,
Jul 24, 2002, 4:19:54 PM7/24/02
to

Doug Harrison wrote:
[...]

> >> FWIW, I've been arguing this point for eight years, and I've never
> >> heard a reasonable argument why catch(...) should catch untranslated
> >> Win32 structured exceptions.
> >
> >It should. And that's non-issue [implementation-defined unwinding and
> >"similar" problems {IMO} with C++ ex.specs. aside] if you catch *ONLY*
> >things you KNOW/REALLY want/need, AFAICS.
>
> Well, no. The point is that catch(...) catches non-C++ exceptions,
> which destroys its usefulness for catching C++ exceptions.

My, consider the following "mixture" of C/SEH and C++ exceptions:

C:\Documents and Settings\Terekhov>cl /EHsc seh3.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.00.9466 for 80x86
Copyright (C) Microsoft Corporation 1984-2001. All rights reserved.

seh3.cpp
Microsoft (R) Incremental Linker Version 7.00.9466
Copyright (C) Microsoft Corporation. All rights reserved.

/out:seh3.exe
seh3.obj

C:\Documents and Settings\Terekhov>seh3
....1
A: done.
....2
B: done.
....wanna rely on SEH for argument validation....
....3
C: done.
....throw std::invalid_argument exception....
A: oh, caught something!
....throw std::invalid_argument exception....
B: oh, caught something!
....wanna rely on SEH for argument validation....
C: oh, caught something!

C:\Documents and Settings\Terekhov>type seh3.cpp

#include <windows.h>

#include <exception>
#include <iostream>

void do_something_A( const int* save_this_value,... )
{
if ( 0 != save_this_value ) {
if ( IsBadReadPtr( save_this_value, sizeof( *save_this_value ) ) ) {
std::cout << "....throw std::invalid_argument exception...." << std::endl;
throw std::invalid_argument("");
}
std::cout << "...." << *save_this_value << std::endl;
/**/
}
/**/
}

void invalid_B_arg()
{
std::cout << "....throw std::invalid_argument exception...." << std::endl;
throw std::invalid_argument("");
}

int load_B_arg( const int* save_this_value )
{
_try {
return *save_this_value;
}
_except( GetExceptionCode() == STATUS_ACCESS_VIOLATION ) {
invalid_B_arg();
}
return 0; // shut up, stupid
}

void do_something_B( const int* save_this_value,... )
{
if ( 0 != save_this_value ) {
int value = load_B_arg( save_this_value );
std::cout << "...." << value << std::endl;
/**/
}
/**/
}

void do_something_C( const int* save_this_value,... )
{
if ( 0 != save_this_value ) {
std::cout << "....wanna rely on SEH for argument validation...." << std::endl;
int value = *save_this_value;
std::cout << "...." << value << std::endl;
/**/
}
/**/
}

int main()
{
int value = 1;
do_something_A( &value );
std::cout << "A: done." << std::endl;
value = 2;
do_something_B( &value );
std::cout << "B: done." << std::endl;
value = 3;
do_something_C( &value );
std::cout << "C: done." << std::endl;
try {
do_something_A( reinterpret_cast< const int* >(1) );
}
catch(...) {
std::cout << "A: oh, caught something!" << std::endl;
}
try {
do_something_B( reinterpret_cast< const int* >(2) );
}
catch(...) {
std::cout << "B: oh, caught something!" << std::endl;
}
try {
do_something_C( reinterpret_cast< const int* >(3) );
}
catch(...) {
std::cout << "C: oh, caught something!" << std::endl;
}
}

C:\Documents and Settings\Terekhov>

regards,
alexander.

Alexander Terekhov

unread,
Jul 24, 2002, 4:24:12 PM7/24/02
to

David Abrahams wrote:
[...]

> Uh, yeah, now that you mention it: on the reality side, my standard library
> implementation is likely to use catch(...) anyway.

< a couple of days earlier >

Alexander Terekhov wrote:
>
> David Abrahams wrote:
> [...]
> > How would you write uninitialized_fill without catch(...)?
>
> Show me the code, please.
>
> [...]
> > Yeah, but if you're interfacing with other peoples' libraries, or writing
> > templates, or writing frameworks that supply base classes with virtual
> > functions, you don't always have control over the types of exceptions that
> > get thrown. Writing certain kinds of exception-neutral code efficiently can
> > be extremely difficult without catch(...).
>
> Examples?

< Still no reply; Okay, "Bringing the mountain to Mmm.." er. Abrahams ;-) >

C:\IBMCPP40\include\memory

------
<snip>
/********************************************************************/
/* <memory> header file */
/* */
/* VisualAge C++, Version 4.0 */
/* Licensed Material - Property of IBM */
/* */
/* 5801-AAR and Other Materials */
/* */
/* (c) Copyright IBM Corp 1991, 1998. All rights reserved. */
/* */
/* */
/* Licensed Materials. */
/* */
/* Dinkum C++ Library */
/* Copyright (c) 1998. Licensed to IBM Corp. and its suppliers. */
/* */
/********************************************************************/
<snip>
// TEMPLATE FUNCTION uninitialized_fill
template<class _FI, class _Ty> inline
void uninitialized_fill(_FI _F, _FI _L, const _Ty& _X)
{for (; _F != _L; ++_F)
_Construct(&*_F, _X); }

<snip>
/*
* Copyright (c) 1995 by P.J. Plauger. ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
*/

/*
* This file is derived from software bearing the following
* restrictions:
*
* Copyright (c) 1994
* Hewlett-Packard Company
<snip>
------


C:\Program Files\Microsoft Visual Studio\VC98\Include\memory

------
<snip>
// TEMPLATE FUNCTION uninitialized_fill
template<class _FI, class _Ty> inline
void uninitialized_fill(_FI _F, _FI _L, const _Ty& _X)
{for (; _F != _L; ++_F)
_Construct(&*_F, _X); }

<snip>
/*
* Copyright (c) 1995 by P.J. Plauger. ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
*/

/*
* This file is derived from software bearing the following
* restrictions:
*
* Copyright (c) 1994
* Hewlett-Packard Company
<snip>
------


C:\Program Files\Microsoft Visual Studio .NET\Vc7\include\memory:

------
<snip>
// TEMPLATE FUNCTION uninitialized_fill
template<class _FwdIt,
class _Tval> inline
void uninitialized_fill(_FwdIt _First, _FwdIt _Last, const _Tval& _Val)
{ // copy _Val throughout raw [_First, _Last)
_Uninit_fill(_First, _Last, _Val, _Ptr_cat(_First, _First));
}

template<class _FwdIt,
class _Tval> inline
void _Uninit_fill(_FwdIt _First, _FwdIt _Last, const _Tval& _Val,
_Nonscalar_ptr_iterator_tag)
{ // copy _Val throughout raw [_First, _Last), arbitrary type
_FwdIt _Next = _First;

_TRY_BEGIN
for (; _First != _Last; ++_First)
_Construct(&*_First, _Val);
_CATCH_ALL
for (; _Next != _First; ++_Next)
_Destroy(&*_Next);
_RERAISE;
_CATCH_END
}

<snip>
/*
* Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
* Consult your license regarding permissions and restrictions.
*/

/*
* This file is derived from software bearing the following
* restrictions:
*
* Copyright (c) 1994
* Hewlett-Packard Company
<snip>
----


C:\Documents and Settings\Terekhov\ABRAuhmmCADABRA.cpp:

----
<snip>

template< class _FwdIt >
class _Uninit_fill_cleanup {
_FwdIt const& m_First;
_FwdIt const& m_Last;
_FwdIt m_Next;
public:

_Uninit_fill_cleanup( _FwdIt const& _First, _FwdIt const& _Last ) :
m_First( _First ), m_Last( _Last ), m_Next( _First ) {
}

~_Uninit_fill_cleanup() {
if ( m_First != m_Last )
for (; m_First != m_Next; ++m_Next)
_Destroy(&*m_Next);
}

};

template< class _FwdIt, class _Tval >
inline void _Uninit_fill( _FwdIt _First, _FwdIt _Last, const _Tval& _Val ) {
_Uninit_fill_cleanup< _FwdIt > _Cleanup( _First, _Last );
for (; _First != _Last; ++_First)
_Construct(&*_First, _Val);
}

<snip>
---

< dreams on >

template< context > // see "10-o'clock-wish-list"
class _Uninit_fill_cleanup {
typeof( context._First ) m_Next;
public:

_Uninit_fill_cleanup() :
m_Next( context._First ) {
}

~_Uninit_fill_cleanup() {
if ( context.m_First != context.m_Last )
for (; context.m_First != m_Next; ++m_Next)
_Destroy(&*m_Next);
}

};

template< class _FwdIt, class _Tval>
inline void _Uninit_fill( _FwdIt _First, _FwdIt _Last, const _Tval& _Val ) {
_Uninit_fill_cleanup< context > _Cleanup();
for (; _First != _Last; ++_First)
_Construct(&*_First, _Val);
}

< dreams off >

regards,
alexander.

Alan Griffiths

unread,
Jul 25, 2002, 7:03:54 AM7/25/02
to
"Ken Hagan" <K.H...@thermoteknix.co.uk> wrote in message news:<1027329701.3321.0...@news.demon.co.uk>...

> "Alan Griffiths" <al...@octopull.demon.co.uk> wrote ...
> >
> > It has been a while since I used VC++ (and things may have changed),
> > but I remember catch (...) sometimes trapped normal OS SEHs that would
> > otherwise be "resumed" without the application being aware that
> > anything had happened. Having unwound the stack this meant that there
> > was no way to recover.
>
> [off topic, at least for clc++m, but this is presented as a killer VC design
> bug
> sufficiently often that non-MSVC users might appreciate the clarification]
>
> Unless you use signals, this isn't true.

[Still off topic, but it may shed light on the claims.]

I'm pleased to know it isn't true now - but it was at one time.
(Having lost several days of my life identifying the problem. This
would have been around 1994-1996.)

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Doug Harrison

unread,
Jul 26, 2002, 11:46:00 AM7/26/02
to
Alexander Terekhov wrote:

>
>Doug Harrison wrote:
>[...]
>> >> FWIW, I've been arguing this point for eight years, and I've
>> never >> heard a reasonable argument why catch(...) should catch
>> untranslated >> Win32 structured exceptions. >
>> >It should. And that's non-issue [implementation-defined unwinding
and
>> >"similar" problems {IMO} with C++ ex.specs. aside] if you catch
*ONLY*
>> >things you KNOW/REALLY want/need, AFAICS.
>>
>> Well, no. The point is that catch(...) catches non-C++ exceptions,
>> which destroys its usefulness for catching C++ exceptions.
>
>My, consider the following "mixture" of C/SEH and C++ exceptions:

Sorry, no. If you want me to look at a long piece of code, you should
take the time to explain it in a sentence or two. In any event, I
understand how SEH can be used in a C++ program, and it isn't relevant.
I thought my statements above and in the threads I cited were clear, but
let me try again. It should be possible to write a C++ program for
Windows without worrying about SEH. If catch(...) catches untranslated
SEs, and you use catch(...), this is impossible. I've given numerous
reasons why this is bad in the threads I linked to, and I expanded upon
one reason in the part of my last message you didn't respond to.

--
Doug Harrison
d...@mvps.org

Alexander Terekhov

unread,
Jul 26, 2002, 4:15:00 PM7/26/02
to

Doug Harrison wrote:
[...]

> >My, consider the following "mixture" of C/SEH and C++ exceptions:
>
> Sorry, no. If you want me to look at a long piece of code, you should
> take the time to explain it in a sentence or two.

Explanation [``in a sentence or two'']:

Moral #1: Don't use "unchecked" ["checked" via ex.specs; harmful
unwinding aside] catch(...)-idiom; use RAII/destructors instead.

Moral #2: Except that you really want "throw" ``INTERNAL_ERROR''
status/return code(s) on the poor face of your exception-less
callers, or perhaps, *re-throw* original exception [whatever it
is]... being extremely careful with respect to the danger of
replacing it with something ELSE -- thrown inside that silly
"(...)-handler" prior to "throw;".

> In any event, I understand how SEH can be used in a C++ program,

That's good.

> and it isn't relevant.

Uhmm. I'd say that nonintegrated SEs are simply "incomplete" C++
exceptions that can be intercepted in pure C++ {only} via catch(...)
if you really want/need it. I personally see NO reasons for doing
it in [pure] C++ to begin with, however. So, yeah, it's totally
irrelevant; indeed. ;-)

> I thought my statements above and in the threads I cited were clear,
> but let me try again. It should be possible to write a C++ program for

> Windows without worrying about SEH. If catch(...) catches untranslated

> SEs, and you use catch(...), this is impossible.

See #1/#2 above.

> I've given numerous
> reasons why this is bad in the threads I linked to, and I expanded
> upon one reason in the part of my last message you didn't respond to.

Well, you wrote:

: In your example, you threw a C++ exception when you shouldn't have,

Why so?

: and it could be caught by a std::exception handler, not just
catch(...).

Agreed. Catching using std::exception "handlers" is pretty much
the same as catching via catch(...)-thing; see #1/#2 above.

: There's no expectation of different behavior here.

Agreed.

: C++ exception handlers are supposed to catch C++ exceptions!

See <wink>-paragraph above.

: So while you may have a bug, I don't believe you have any reason
: to complain.

FULLY AGREED!!! ;-) Bugs should end up in "core dumped"/JIT-
debuggers/etc. as soon as possible [to prevent further damage, to begin
with]... even if "manifested" via *unexpected* {C++
and/or nonintegrated C/SEH, whatever} exceptions.

regards,
alexander.

Reply all
Reply to author
Forward
0 new messages