Are exceptions standardized in C++? I mean if the rules of exception handling might be changed in the future.

i.e:

 int Funct1(int) throw(); // does it throw an exception?

Recommended Answers

All 3 Replies

Yes, exceptions are standardized, and all compilers that I am aware of handle them correctly (not always the case in the mid-90's). This signature indicates that Funct1(int) may (or may not) throw an exception. In any case, throw() specifies that it may throw ANY exception. Usually you specify what exception type(s) it may throw. Your usage is a "catch-all". Caveat programmer! :-)

Just a bit of history. In the early-mid 1990's we were writing application development frameworks and applications in C++ that had to run on many different Unix systems (and Windows as well as embedded systems), so consistent exception handling was required. I wrote a recursive routine to compute fibonacci numbers using exceptions to test them. You would be surprised how many failed that test! Let's just say that a lot of major corporate VP's of engineering had some interesting phone calls (Sun, IBM, HP, DEC, et al). Needless to say, since we were a major partner for all of them, the problems were resoved PDQ. In any case, this was not the only compiler issue with many of them. I'm sure that to this day, I am remembered "fondly" by many!

As for the rules changing in the future - it may happen, but probably not - Bjarne would roll over in his grave if he is not around by then! :-)

Usually you specify what exception type(s) it may throw.

Noting of course that exception specifications have been deprecated because they're stupid. Support for exceptions themselves is still standardized and unlikely to change significantly in the forseeable future.

In any case, throw() specifies that it may throw ANY exception.

That's wrong. Maybe you forgot the negative in that statement, it should say: "throw() specifies that it may NOT throw ANY exception."

Here is the whole story. Exceptions are standardized in the C++ ISO Standard document. Their behavior is fully specified and compilers mostly comply to that specification, and have done so for a couple of decades now (at the very least, since 2000 or so). The behavior of exceptions is specified in terms of how the stack should be unwound following the throwing of an exception, what should happen in special cases (e.g., calls std::terminate() if an exception is thrown during the stack unwinding (e.g., from a destructor)), and how the appropriate "catch" statement is selected. That's all the "observable" behavior that is specified.

Note, however, that the standard says nothing about the implementation of those behaviors, i.e., compiler-vendors are free to implement those mechanisms any way they see fit, as long as it behaves correctly. However, most compilers comply with the Intel Itanium C++ ABI standard which has a detailed and standardized description of the so-called "zero cost exception handling" implementation, see here. In fact, the only modern compiler that does not implement and comply to the Itanium ABI standard is the Microsoft compiler (MSVC), which is, of course, the last compiler you would use if you care about standardization or reliability at all (i.e., MSVC is not really a production-quality compiler).

So, if you combine the C++ standard and the Itanium standard, then you pretty much get a full standardization of every detail about how exceptions work.

I mean if the rules of exception handling might be changed in the future.

Yes and no. It is extremely unlikely that anything will be changed in a way that would break existing code, i.e., changes will always remain backward compatible. At least, as far as the actual exception handling behavior is concerned, that is, the things that I mentioned above (stack unwinding, catch selection, etc.). What has changed recently (C++11), and could change further, is in the form of additional features (e.g. std::exception_ptr) and changing the exception specification rules (i.e., the throw() and throw(something, something) specifications on functions).

The additional features, such as std::exception_ptr, std::current_exception and std::rethrow_exception, simply provide additional introspection about the exceptions. They just give you additional power to deal with the exceptions. That did not break existing (pre-C++11) exception handling standards, it just adds convenient features to it (at no cost).

The exception specification rules were a really terrible idea to begin with, and they have been deprecated because they nobody used them because they were impractical. The only form of exception specification that made any kind of practical sense was the empty specification throw() which says "no exception will be thrown from this function". However, even the throw() specification is still kind of problematic, because it doesn't go far enough. This specification is still OK in C++11, but, in general, it is preferred to use the new specification called noexcept.

The throw() specification means that no exception can be thrown from that function, that's the easy part. The more subtle part is that if an exception is thrown within that function, the compiler is required to unwind the stack up to when it is about to leave the no-throw function. At that point, the exception would become an "unexpected" exception, which would normally cause a call to std::terminate() (i.e., hard-stop of the program). The problem here is that a function marked as throw() still needs to be handled by the compiler as a function that could throw an exception, except that it needs to add some code to terminate the application if that occurs.

So, the new specification, by the noexcept keyword, changes that behavior in a very meaningful way. The noexcept says, as with throw(), that the function will not throw. However, the stack is not required to be unwound when an exception is thrown in it. It could be unwound (behaving as throw()), but it could also be left as is, i.e., calling std::terminate() immediately. To the average programmer, this makes very little difference, because in both cases, the overall behavior is that the program terminates in a crash when an exception is thrown within a no-throw / no-except function. However, to the compiler, this makes a big difference in terms of optimizations because it can assume that it never has to prepare for a possible stack-unwinding, which allows deeper static analysis and better optimizations. Some compilers already implement this (GCC, Clang, at least).

So, I hope this gives you a pretty complete picture, and allows you to understand how things can change, but won't change in a way that seriously breaks anything, and generally just change for the better (add feature, get more useful specified behavior, etc.).

commented: I stand/sit corrected! Thanks Mike. +0
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.