Exception Specifications

K

Keith Halligan

I'm a bit unsure about exception specifications and the rules that
they enforce.

I've had a look at the C++ spec and it doesn't state about the errors
that it enforces, if an exception is thrown in a function that isn't
specified in its exception specification (assuming there's one
there).

If I compile the code below on Solaris, Linux and AIX, I get the
program coring, causing the "std::exception" to be thrown back to the
runtime and the "catch (std::exception)" is not handled.

However if I run this on Windows (VC++6 and VC++8), the "catch
(std::exception") handler is used.

I know this is going a bit platform specific, but I'm just wondering
what the proper behaviour for C++ should be?

I would expect the Unix platforms to have the correct behaviour as we
are invalidating the exception specifier so that should *not* be
allowed.


=========================================
#include <iostream>
#include <exception>

class sys_exception { };

void f ( ) throw (sys_exception)
{
throw std::exception( );
}

int main ( )
{
try
{
f( );
}
catch (sys_exception& se)
{
std::cerr << "System Exception thrown" << std::endl;
}
catch (std::exception& e)
{
std::cerr << "Exception thrown" << std::endl;
}
catch (...)
{
std::cerr << "Unknown Exception thrown" << std::endl;
}

return 0;
}
===================================

Cheers,
- Keith
 
R

Rolf Magnus

Keith said:
If I compile the code below on Solaris, Linux and AIX, I get the
program coring, causing the "std::exception" to be thrown back to the
runtime and the "catch (std::exception)" is not handled.

However if I run this on Windows (VC++6 and VC++8), the "catch
(std::exception") handler is used.

I know this is going a bit platform specific, but I'm just wondering
what the proper behaviour for C++ should be?

std::unexpected() should be called, which in turn calls the unexpected
handler, which by default (if you didn't specify another one) calls
std::terminate, which calls the terminate handler, which by default calls
abort().
I would expect the Unix platforms to have the correct behaviour as we
are invalidating the exception specifier so that should *not* be
allowed.

Yes. The whole point of exception specifications is that the caller can be
100% sure that the function does never throw any exception that is not
mentioned in the specification.
 
K

Keith Halligan

std::unexpected() should be called, which in turn calls the unexpected
handler, which by default (if you didn't specify another one) calls
std::terminate, which calls the terminate handler, which by default calls
abort().

The spec does mention this alright, I modified the code to make use of
them on Linux and yes I can alter how the termination works via
std::set_unexpected() and std::set_terminate() functions, to stop the
abort from occurring.

So with this in mind then Visual C++ is incorrect in following the
spec.
 
E

Erik Wikström

The spec does mention this alright, I modified the code to make use of
them on Linux and yes I can alter how the termination works via
std::set_unexpected() and std::set_terminate() functions, to stop the
abort from occurring.

So with this in mind then Visual C++ is incorrect in following the
spec.


Yes, VS only supports the empty (nothrow) exception specifier.
 
M

Martin York

Yes, VS only supports the empty (nothrow) exception specifier.

Exception specifications is one of those ideas that did not really
work.

The generally except way of using them is not to use them (with the
exception of no throw).
The last thing (in most situations) you actually want your application
to do is terminate with extreme prejudice. NB: when terminate() is
called, non of your outstanding destructor's are called and no clean
up is done.

If you do use them them make sure you catch anything that will kill
your program. Unless you want it to die.

void doStuff() throw (X,Y)
{
try
{
}
catch(const X& x) {throw;}
catch(const Y& y) {throw;}
catch(...)
{
// Something crazy happened must
// cleanup and do something special
// a re-throw will terminate the code
// But an error happened (help)
}
}
 
J

James Kanze

Exception specifications is one of those ideas that did not really
work.

It works fine for me.

The problem is that it has been explained in a way that leads
people to believe it does something that it doesn't, and which
in fact isn't possible. What it does do is implement a very
small part of programming by contract; you contract NOT to throw
any exceptions other than the ones listed, and the compiler
generates code to enforce that contract. (In practice, of
course, the only really useful contract in this case is no
exceptions.)
The generally except way of using them is not to use them (with the
exception of no throw).

Which is a major exception.
The last thing (in most situations) you actually want your
application to do is terminate with extreme prejudice.

If there is a violation of the contract, that's exactly what you
want to happen. If the program is not working correctly, it is
important for it to terminate as quickly as possible, with as
much prejudice as possible, so the system can take whatever
steps are necessary in such cases.
 
M

Martin York

It works fine for me.

The problem is that it has been explained in a way that leads
people to believe it does something that it doesn't, and which
in fact isn't possible.

I agree.
What it does do is implement a very
small part of programming by contract; you contract NOT to throw
any exceptions other than the ones listed, and the compiler
generates code to enforce that contract. (In practice, of
course, the only really useful contract in this case is no
exceptions.)


Which is a major exception.

But we agree.
If there is a violation of the contract, that's exactly what you
want to happen. If the program is not working correctly, it is
important for it to terminate as quickly as possible, with as
much prejudice as possible, so the system can take whatever
steps are necessary in such cases.

It is only in the most exceptional cases that I want my application to
finish without tidying up after itself. Yes I want this facility but
this is the exception (no pun intended) not the rule.

If I detect an unexpected exception (ie a contract was broken) I may
want the application to finish (trying to avoid the word terminate)
but I would rather unwind the stack and make sure all the destructor's
are called so that all my resources are nicely cleaned up and then
finish the application.

But notice the key word here is (detected). We have detected the
breach in contract so there is a possibility that we could do
something about it, probably not a lot we can do but we don't need to
penalize other applications (ie your DB because the connection is
unexpectedly been severed) because our client has misbehaved.

But we are talking very much in generalities here and each situation
is unique and will require its own analysis.
Yes we both agree that the application should terminate (probably as
quickly as possible). I just don't think terminate() is a good idea in
most situations and thus my tendency not to use exception
specifications unless I have a high level of control.
 
J

James Kanze

On May 5, 3:06 am, James Kanze <[email protected]> wrote:

[...]
It is only in the most exceptional cases that I want my
application to finish without tidying up after itself.

Violation of contract is a programming error. Hopefully,
programming errors are very exceptional cases in your
application. If you have a programming error (e.g. assertion
failure), something has happened that you know couldn't happen.
That means that your reasoning about the code was wrong,
somewhere. So "tidying up" isn't going to do what you thought
it would either, and is in fact likely to make things worse.
Yes I want this facility but this is the exception (no pun
intended) not the rule.

Think of "throw()" as simply "assert(won't exit by exception)".
That's really what it comes down to. In specific cases, it's a
very important part of the contract, and it's definitly worth
asserting.
If I detect an unexpected exception (ie a contract was broken)
I may want the application to finish (trying to avoid the word
terminate) but I would rather unwind the stack and make sure
all the destructor's are called so that all my resources are
nicely cleaned up and then finish the application.
But notice the key word here is (detected). We have detected
the breach in contract so there is a possibility that we could
do something about it, probably not a lot we can do but we
don't need to penalize other applications (ie your DB because
the connection is unexpectedly been severed) because our
client has misbehaved.

In real life, other applications (or other programs in the same
application) have to be able to handle an abrupt termination of
your program. Because that's the way systems work: some errors
will lead to an assertion failure, or terminate() being called;
others will cause the system to terminate the program
immediately, no questions asked.

The case of throw() is particularly special, because normally,
if you're using it, it is because not throwing is an essential
part of the contract; the stack is (temporarily) in a state
where stack walkback isn't possible. (Consider what would
happen if std::swap threw while you were swapping pointers in
the swap idiom of assignment.)
But we are talking very much in generalities here and each
situation is unique and will require its own analysis.

Yes. There are applications where it is better to stumble on,
and hopefully be able to recover something. (Games come to
mind.) I suppose a compiler with an option to turn it off (much
as you can turn off assertions) might be useful. The default,
however, should be like assertions: on (and I've never delivered
code with assertions turned off).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top