Can anyone explain Exception Specifications as used in C++ ?
When are they used (I have rarely seen it used in code)
What are the pros and cons (benefits/disadvantages) of using exception specifications?
When are they used (I have rarely seen it used in code)
Hopefully never as they are deprecated in the next version of C++ due for standardization next year.
What are the pros and cons (benefits/disadvantages) of using exception specifications?
They provide a way for readers of your code to know exactly what exceptions a function is allowed to throw. The problem is, that if an unexpected exception (one not in the specification) is thrown, then the program will be terminated (by default).
They are generally regarded as a bad idea.
They say what a method will throw. The downside is that if that method throws anything else then your app terminates. So it's a guarantee but not in the same way that Java does it. And it adds the overhead of inspection.
The important thing to know is: exception specifications are deprecated in the next revision of C++, except for the no-throw specifier (throw()), which is basically officially saying "don't use them".
Putting throw() after a function means the function does not throw any exceptions. If it does anyway, the application will be terminated (probably - the unexpected handler is called), so the rest of your application can use that function knowing it will not throw an exception. This is can be handy for writing exception-safe code.
Example:
void MyFunction() throw() // does not throw any exceptions
{
/* ... */
{
They indicate to the programmer which exceptions will be thrown from that function. They have the advantage that you have the guarantee that no other exceptions can be thrown from that function. However, there is no compile-time checking of whether the function actually throws any exceptions other than what is indicated in the throw specifier. Instead, it's checked at runtime. And if it fails, then unexpected() is called, which by default calls abort() which in turn by default terminates your program. So, unless you really want your program to die if you screw up and an unexpected exception gets thrown, it's probably a bad idea to use them.
The one place where I would actually recommend using them is on destructors. It's really bad if a destructor throws. They should never throw. So, if you use throw() on a destructor to indicate that it can't throw an exception, then you know that your program will die rather than continue in the bad state that it would be in after an exception was thrown from a destructor.
Regardless, if you use any kind of throw specifier, you have to be sure that you really do want your program to die if it's violated. So, generally-speaking, it's best not to use them.
Basically, exception specifications allow the compiler to optimize the stack. The disadvantage is that it's a hell of a lot of extra spec. This means that you commonly see it in library work but not so much in working code.
I believe there's also some compile-time exception-safety thing going on, but since I've never used it, I can't be sure.
Related
From man gcc:
-fno-enforce-eh-specs
Don't generate code to check for violation of exception specifications
at run time. This option violates the C++ standard, but may be useful
for reducing code size in production builds.
When a compiler optimizes, it removes all sorts of checks, it breaks the boundaries between functions, it might even avoid things like system calls the developer put in the code in some cases. So:
Why is exception specification violation checking so special that it cannot be skipped?
What exactly is being checked?
If using this switch is so useful for reducing code size, how come the C++ standard requires these checks? I thought the idea is zero-overhead abstractions whenever possible.
The (now old?) standard requires that a function declared void f() throw(x); must not throw any exception other than x (or possibly derived from x?). If it tries to throw something else, std::unexpected() should be called, and probably end up in a call to std::terminate() to kill the program.
But if the exact type of the exception cannot be determined at compile time, a run-time check might be needed to determine if the exception is of an acceptable type.
Of course, if that check is removed by this option, an incorrect exception might escape from the function. And that would be a violation of the standard.
Why is exception specification violation checking so special that it cannot be skipped?
What exactly is being checked?
This has been answered already, but for completeness in my answer as well: for functions with throw(...) and noexcept specifications, when exceptions get thrown that are not permitted, std::unexpected() or std::terminate() must be called.
Effectively, they turn something like
void f();
void g() noexcept { f(); }
into something very similar to:
void f();
void g() { try { f(); } catch (...) { std::terminate(); } }
If using this switch is so useful for reducing code size, how come the C++ standard requires these checks? I thought the idea is zero-overhead abstractions whenever possible.
Indeed. But there is no way to implement this without overhead. Compilers do already manage to implement exceptions in such a way that the code that gets executed at run-time, as long as no exceptions are thrown, is identical to the version without exception handling. In that sense, on platforms with suitable ABIs, zero-overhead exceptions has been achieved. They, however, do still annotate that code with special markers that lets the run-time library figure out what code to call when exceptions do end up thrown. Those special markers take up space. The code that ends up interpreting those markers takes up space as well. And the actual exception handling code, even if it's only std::terminate(), takes up yet more space.
Although this topic has been extensively discussed on SO, I'd like to clarify a few things that are still not clear to me so, considering the following facts:
10 years ago, Herb Sutter was telling us to refrain from using this functionality.
Specifying the possible exceptions that a function / method may throw does not force the compiler to yell at you when you decide to change the function's body and throw a new type of exception, forgetting by mistake to change the exception specification in the function's declaration.
If you have a very high level function that calls several other high level functions, which each run tons of code to produce the results, then I can imagine the maintenance from hell nightmare, when I would have to specify ALL the errors which the first function may throw, and this list would have to include all the exceptions the inner functions may throw and so on, thus creating tight coupling between high and low level functions, which is quite undesirable. On the other hand, we derive all exceptions from std::runtime_error, which we know is a good practice and we could specify that the high level functions just throw std::runtime_error and be done with it. But wait a minute... Where do we actually catch the exceptions? Would it not be rather odd / nasty / bad to enclose a call to one of these high level functions in a try / catch block, which catches a MyVerySpecific exception, when the high level function is supposed to throw only std::runtime_error??? Would it be any good to catch specific exceptions in lower level functions, which are not able to do anything about them but pass them on in a more generic container, with more information appended to them? I certainly don't want to write try / catch blocks in every function that I write, just to format exceptions. It would be like requiring every function to validate its parameters, and that can drive people insane, when they need to change something in a low level function.
Questions:
Do Herb Sutter's rants about exception specification still hold today? Has anything changed since then? I am mostly interested in pre-C++0x standards. If yes, I guess we can consider this topic closed.
Since it seems that the compiler mostly ignores these exception specifications, and when catching exceptions, in 99% of the cases, one would use catch (const CustomException &ex), how would one specify that a function throws CustomException? throw(CustomExecption) or throw (CustomException &) or throw (const CustomException &)? I have seen all variations, and, although I would go for the first one, do the others make any sense / add any benefits?
How would one actually use this functionality, and, at the same time, avoid the fallacies illustrated in the above 3rd fact?
EDIT: Suppose that we're building a library. How will its users know what exceptions to expect, if we don't use exception specification? They will certainly not see what functions will be called internally by the API methods...
1/ Do Herb Sutter's rants about exception specification still hold today? Has anything changed since then? I am mostly interested in pre-C++0x standards. If yes, I guess we can consider this topic closed.
Yes, they still hold.
Exceptions specifications are:
half-way implemented (function pointers don't specify exceptions, for example)
not checked at compile-time, but leading to termination at runtime !!
In general, I would be against exceptions specifications, because it causes a leak of implementation details. Look at the state of Java exceptions...
In C++ in particular ? Exceptions specifications are like shooting yourself in the foot since the tiniest error in documentation may lead to a std::terminate call. Note that almost all functions may throw a std::bad_alloc or a std::out_of_range for example.
Note: Since C++11, throw() was deprecated and now with C++17 it is gone; instead, from C++17 on, the noexcept(false) specifier can be used. It is better supported in function pointers, but still leads to termination at run-time rather than errors at compile-time.
2/ Since it seems that the compiler mostly ignores these exception specifications, and when catching exceptions, in 99% of the cases, one would use catch (const CustomException &ex), how would one specify that a function throws CustomException? throw(CustomExecption) or throw (CustomException &) or throw (const CustomException &)? I have seen all variations, and, although I would go for the first one, do the others make any sense / add any benefits?
The compiler does not ignore the exceptions specifications, it sets up very vigilant watchdogs (which axes) to make sure to kill your program in case you had missed something.
3/ How would one actually use this functionality, and, at the same time, avoid the fallacies illustrated in the above 3rd fact?
Your customer will appreciate if it stays informal, so the best example is:
void func(); // throw CustomException
and this lets you focus on the exceptions that matter too, and let "unimportant" exceptions slip through. If a consumer wants them all ? catch(std::exception const& e) works.
4/ EDIT: Suppose that we're building a library. How will its users know what exceptions to expect, if we don't use exception specification? They will certainly not see what functions will be called internally by the API methods...
Do they have to ?
Document what matters, std::exception or ... take care of the unexpected.
Do Herb Sutter's rants about exception specification still hold today? Has anything changed since then?
I wouldn't call that a rant. He just pointed out problems related to exception specifications.
Yes, it still holds. As explained in the text, if a not specified exception is throw, the program terminates, and that is not acceptable for 99% applications.
how would one specify that a function throws CustomException?
class A
{
//...
void foo() throws( CustomException );
};
How would one actually use this functionality, and, at the same time, avoid the fallacies illustrated in the above 3rd fact?
By looking at the function declaration, the user knows which exceptions can be thrown. The problem is when a new exception needs to be thrown, then all functions declarations needs to be changed.
Suppose that we're building a library. How will its users know what exceptions to expect, if we don't use exception specification?
By reading the documentation.
In C++ you may declare function with exception specification like this:
int foo() const throw(Exception);
I found those two links:
http://www.cplusplus.com/doc/tutorial/exceptions/ and
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fcplr156.htm
But several things end up unanswered...
Question 1: why to add exception specification? Will it bring any performance increase? What will be different for compiler? Because it seems just like an information for programmer to me.
Question 2: what will happend (what should happen) if I throw something that isn't in specification? For example:
int foo() throw(int) {
throw char; // Totally unrelated classes, not types in real
}
Question 3: function/method shouldn't throw anything. I found at least two (three, alternative syntax for different compilers) ways to specify no exception throwing:
int foo() throw();
int foo() __attribute(nothrow)__ for gcc
int foo() nothrow for visual C++
Which one is "correct"? Is there any difference? Which one should I use?
Question 4: "standart exceptions", bad_alloc,bad_cast,bad_exception,bad_typeid and ios_base::failure.
Ok bad_alloc is self explaining and I know how (and more importantly when) to use it (add to exception specification), but what about the others? None of them does really ring a bell... Which "code pieces" are they associated with? Like bad_alloc is associated with new char[500000].
Question 5: If I have exception classes hierarchy, like this:
class ExceptionFileType {
virtual const char * getError() const = 0;
};
class ExceptionFileTypeMissing : public ExceptionFileType {
virtual const char *getError() cosnt {
return "Missing file";
}
}
Should I use:
int foo() throw(ExceptionFileType);
Or:
int foo() throw(ExceptionFileTypeMissing,ExceptionFileTypeNotWritable,ExceptionFileTypeNotReadable,...)
Note: answers with references would be great. I'm looking for good practice tips.
The simple "good practice" tip is: don't use exception specifications.
Essentially the only exception to that is the possibility of an empty exception specification: throw(). That's sufficiently useful that in C++11 it's been given its own keyword (noexcept). It's generally agreed that any non-empty exception specification is a lousy idea though.
Exception specifications (other than noexcept) are officially deprecated -- and unlike many deprecated features, removing this would affect little enough source code that I think there's a good chance it really will eventually be removed (certainly no guarantee, but a pretty fair chance anyway).
As for what happens when/if you do throw an exception of a type not allowed by the exception specification: std::unexpected() gets invoked. By default, that invokes terminate(). You can use std::set_unexpected to set your own handler -- but about all you can reasonably do is add some logging before you terminate(). Your unexpected handler is not allowed to return.
Question 1
Don't bother. They were a bad idea, and were deprecated in the latest version of the language. They give no benefit to the compiler, since they are checked at runtime; if anything, they might hurt performance in some cases.
Question 2
A function called std::unexpected will be called. By default, this calls std::terminate; by default, that terminates the program. Both of these behaviours can be changed, using std::set_unexpected and std::set_terminate to install your own handler, if you really want to.
Question 3
throw() was the standard way to do it; the others are non-portable compiler extensions. In C++11, you might use noexcept, which gives a compile-time check that nothing can throw, rather than a run-time check that nothing does throw.
Question 4
bad_cast is thrown when a dynamic_cast of a reference fails.
bad_exception is thrown in some weird circumstances when an exception specification is violated.
bad_typeid is thrown if evaluating the argument to typeid involves dereferencing a null pointer
ios_base::failure is thrown by the input/output library (<iostream> etc.) when some operations fail
Question 5
If you want to allow the entire heirarchy to be thrown, then just specify the base class. But you shouldn't be using exception specifiers at all.
First, let's be very clear what an exception specification does: it's
more or less like an assert that can't be disabled, asserting that you
will not exit the function with an exception other than the ones
missing. As such, it's utility is far more limited than it would seem
at first; for the most part (and in this case, I can't imagine an
exception), the only really useful guarantee is throw(), which
guarantees that no exception will be thrown; if you want to write
exception safe code, you'll need this guarantee for a few low level
functions.
In practice, although throw() could allow some additional compiler
optimizations, the generic implementation tends to result in less
efficient code when an exception specification is used. In C++11, the
throw() has been replaced by noexcept, presumably with the hope that
compiler implementers will do something intelligent with it.
EDIT:
Since everyone (including myself) seems to have missed your question 4:
bad_alloc will be thrown by the operator new function if it cannot
allocate the memory.
bad_cast will be thrown by a dynamic_cast to a reference, in the
case where the cast fails. (A dynamic_cast to a pointer returns a
null pointer in such cases.)
bad_exception will be thrown when an exception specification is
violated, provided the exception specification allows bad_exception.
(In other words, forget it.)
bad_typeid will be thrown if you try to use typeid with a null
pointer.
ios_base::failure will be thrown if you request a stream to throw in
case of errors.
Practically speaking: you'll catch bad_alloc if you want to recover
and continue from out of memory situations. Which means not very often.
(It's very, very difficult to recover from an out of memory situation.)
For bad_cast, it's probably preferrable to use pointers, and test for
null, if you aren't sure. And there's no excuse for ever seeing a
bad_typeid. Most of the time, you'll probably want to test IO errors
explicitly, rather than configuring the stream to throw exceptions; and
exception when ios_base::badbit is set might be an exception (since it
represents a truly exceptional case of a hardward fault).
Questions 1 and 2 are addressed at some length in this question.
Questions 3 and 5 are covered by the recommendation, in the accepted answer to that question, that you don't use exception specifications at all.
Question 4 seems to be adequately addressed by typing those exception names into the search engine of your choice, or consulting the index of a good C++ book. Do you have a specific query about them?
void MyFunction(int i) throw();
it just tells the compiler that the function does not throw any exceptions.
It can't make sure the function throw nothing, is that right?
So what's the use of throw()
Is it redundant? Why this idea is proposed?
First of all, when the compiler works right, it is enforced -- but at run-time, not compile-time.. A function with an empty exception specification will not throw an exception. If something happens that would create an exception escaping from it, will instead call unexpected(), which (in turn) calls abort. You can use set_unexpected to change what gets called, but about all that function is allowed to do is add extra "stuff" (e.g. cleanup) before aborting the program -- it can't return to the original execution path.
That said, at least one major compiler (VC++) parses exception specifications, but does not enforce them, though it can use empty exception specifications to improve optimization a little. In this case, an exception specification that isn't followed can/does result in undefined behavior instead of necessarily aborting the program.
It can't make sure the function throw nothing, is that right?
You are almost there. It is an exception specification. It means that as an implementer you gurantee to your client(s) that this piece of code will not throw an exception. This does not however stop some functions within MyFunction to throw and which, if you do not handle them, will bubble up and cause your/client's program in a way you did not intent it to. It does not even mean that you cannot have a throw expression inside.
It is best to avoid such specification, until and unless you are absolutely sure that your code will never throw -- which is kind of difficult except for very basic functions. See the standard swap, pointer assignments etc.
Is it redundant? Why this idea is proposed?
Not exactly. When properly used, it can be of help to the compiler for optimization purposes. See this article. This article explains the history behind no-throw well.
Digging a bit more I found this excellent article from the Boost documentation. A must read. Read about the exception guarantees part.
As you said, it just tells the compiler that the function does not throw any exceptions.
When the compiler expects possible exceptions, it often has to generate the code in some specific form, which makes it less efficient. It also might have to generate some additional "household" code for the sole purpose of handling exceptions when and if they are thrown.
When you tell the compiler that this function never throws anything, it makes it much easier to the compiler to recognize the situations when all these additional exception-related expenses are completely unnecessary, thus helping the compiler to generate more efficient code.
Note, that if at run time you actually try to throw something out of a function that is declared with throw() specification, the exception will not be allowed to leave the function. Instead a so called unexpected exception handler will be invoked, which by default will terminate the program. So, in that sense it is actually enforced that a throw() function does not throw anything.
P.S. Since exception specifications are mostly affecting the run-time behavior of the program, in general they might not have any compile time effect. However, this specific exception specification - the empty one throw() - is actually recognized by some compilers at compile time and does indeed lead to generation of more efficient code. Some people (me included) hold the opinion that the empty exception specification is the only one that is really worth using in the real-life code.
To be honest exception specifications in the real world have not turned out to be as usfull as envisoned by the origianl designers. Also the differences between C++ runtime checked exception specifications and Java's compile time checked exception specifications has caused a lot of problems.
The currently except norms for exception specifications are:
Don't use them.
Unless they are the empty form.
Make sure that if you use the empty form gurantee that you actually catch all excetions.
The main problem is that if you have a method with a throw spec. Then somthing it uses changes underneath and now throws new types of exception there is no warning or problem with the code. But at runtime if the exception occurs (the new one that is not in throw spec) then your code will terminate(). To me termination is a last resort and should never happen in a well formed program I would much rather unwind the stack all the way back to main with an exception thus allowing a sliughtly cleaner exit.
In C++, you can specify that a function may or may not throw an exception by using an exception specifier. For example:
void foo() throw(); // guaranteed not to throw an exception
void bar() throw(int); // may throw an exception of type int
void baz() throw(...); // may throw an exception of some unspecified type
I'm doubtful about actually using them because of the following:
The compiler doesn't really enforce exception specifiers in any rigorous way, so the benefits are not great. Ideally, you would like to get a compile error.
If a function violates an exception specifier, I think the standard behaviour is to terminate the program.
In VS.Net, it treats throw(X) as throw(...), so adherence to the standard is not strong.
Do you think exception specifiers should be used?
Please answer with "yes" or "no" and provide some reasons to justify your answer.
No.
Here are several examples why:
Template code is impossible to write with exception specifications,
template<class T>
void f( T k )
{
T x( k );
x.x();
}
The copies might throw, the parameter passing might throw, and x() might throw some unknown exception.
Exception-specifications tend to prohibit extensibility.
virtual void open() throw( FileNotFound );
might evolve into
virtual void open() throw( FileNotFound, SocketNotReady, InterprocessObjectNotImplemented, HardwareUnresponsive );
You could really write that as
throw( ... )
The first is not extensible, the second is overambitious and the third is really what you mean, when you write virtual functions.
Legacy code
When you write code which relies on another library, you don't really know what it might do when something goes horribly wrong.
int lib_f();
void g() throw( k_too_small_exception )
{
int k = lib_f();
if( k < 0 ) throw k_too_small_exception();
}
g will terminate, when lib_f() throws. This is (in most cases) not what you really want. std::terminate() should never be called. It is always better to let the application crash with an unhandled exception, from which you can retrieve a stack-trace, than to silently/violently die.
Write code that returns common errors and throws on exceptional occasions.
Error e = open( "bla.txt" );
if( e == FileNotFound )
MessageUser( "File bla.txt not found" );
if( e == AccessDenied )
MessageUser( "Failed to open bla.txt, because we don't have read rights ..." );
if( e != Success )
MessageUser( "Failed due to some other error, error code = " + itoa( e ) );
try
{
std::vector<TObj> k( 1000 );
// ...
}
catch( const bad_alloc& b )
{
MessageUser( "out of memory, exiting process" );
throw;
}
Nevertheless, when your library just throws your own exceptions, you can use exception specifications to state your intent.
Avoid exception specifications in C++. The reasons you give in your question are a pretty good start for why.
See Herb Sutter's "A Pragmatic Look at Exception Specifications".
I think the standardly except convention (for C++)
Exception specifiers were an experiment in the C++ standard that mostly failed.
The exception being that the no throw specifier is useful but you should also add the appropriate try catch block internally to make sure the code matches the specifier. Herb Sutter has a page on the subject. Gotch 82
In a addition I think it is worth describing Exception Guarantees.
These are basically documentation on how the state of an object is affected by exceptions escaping a method on that object. Unfortunately they are not enforced or otherwise mentioned by the compiler.
Boost and Exceptions
Exception Guarantees
No Guarantee:
There is no guarantee about the state of the object after an exception escapes a method
In these situations the object should no longer be used.
Basic Guarantee:
In nearly all situations this should be the minimum guarantee a method provides.
This guarantees the object's state is well defined and can still be consistently used.
Strong Guarantee: (aka Transactional Guarantee)
This guarantees that the method will complete successfully
Or an Exception will be thrown and the objects state will not change.
No Throw Guarantee:
The method guarantees that no exceptions are allowed to propagate out of the method.
All destructors should make this guarantee.
| N.B. If an exception escapes a destructor while an exception is already propagating
| the application will terminate
gcc will emit warnings when you violate exception specifications. What I do is to use macros to use the exception specifications only in a "lint" mode compile expressly for checking to make sure the exceptions agree with my documentation.
The only useful exception specifier is "throw()", as in "doesn't throw".
Exception specifications are not wonderfully useful tools in C++. However, there /is/ a good use for them, if combined with std::unexpected.
What I do in some projects is code with exception specifications, and then call set_unexpected() with a function that will throw a special exception of my own design. This exception, upon construction, gets a backtrace (in a platform-specific manner) and is derived from std::bad_exception (to allow it to be propagated if desired). If it causes a terminate() call, as it usually does, the backtrace is printed by what() (as well as the original exception that caused it; not to hard to find that) and so I get information of where my contract was violated, such as what unexpected library exception was thrown.
If I do this, I never allow propagation of library exceptions (except std ones) and derive all my exceptions from std::exception. If a library decides to throw, I will catch and convert into my own hierarchy, allowing for me to always control the code. Templated functions that call dependent functions should avoid exception specifications for obvious reasons; but it's rare to have a templated function interface with library code anyway (and few libraries really use templates in a useful manner).
If you're writing code that will be used by people that would rather look at the function declaration than any comments around it, then a specification will tell them which exceptions they might want to catch.
Otherwise I don't find it particularly useful to use anything but throw() to indicate that it doesn't throw any exceptions.
Yes, if you're into internal documentation. Or maybe writing a libary that others will use, so that they can tell what happens without consulting the documentation. Throwing or not throwing can be considered part of the API, almost like the return value.
I agree, they are not really useful for enforcing correctness Java style in the compiler, but it's better than nothing or haphazard comments.
No. If you use them and an exception is thrown that you did not specify, either by your code or code called by your code, then the default behavior is to promptly terminate your program.
Also, I believe their use has been deprecated in current drafts of the C++0x standard.
A "throw()" specification allows the compiler to perform some optimisations when doing code flow analysis if it know that function will never throw an exception (or at least promises to never throw an exception). Larry Osterman talks about this briefly here:
http://blogs.msdn.com/larryosterman/archive/2006/03/22/558390.aspx
Generally I would not use exception specifiers. However, in cases where if any other exception were to come from the function in question that the program would definitively be unable to correct, then it can be useful. In all cases, make sure to document clearly what exceptions could be expected from that function.
Yes, the expected behavior of a non-specified exception being thrown from a function with exception specifiers is to call terminate().
I will also note that Scott Meyers addresses this subject in More Effective C++. His Effective C++ and More Effective C++ are highly recommended books.
They can be useful for unit testing so that when writing tests you know what to expect the function to throw when it fails, but there is no enforcement surrounding them in the compiler. I think that they are extra code that is not necessary in C++. Which ever you choose all that you should be sure of is that you follow the same coding standard across the project and the team members so that your code remains readable.
From the article:
http://www.boost.org/community/exception_safety.html
“It is well known to be impossible to
write an exception-safe generic
container.” This claim is often heard
with reference to an article by Tom
Cargill [4] in which he explores the
problem of exception-safety for a
generic stack template. In his
article, Cargill raises many useful
questions, but unfortunately fails to
present a solution to his problem.1 He
concludes by suggesting that a
solution may not be possible.
Unfortunately, his article was read by
many as “proof” of that speculation.
Since it was published there have been
many examples of exception-safe
generic components, among them the C++
standard library containers.
And indeed I can think of ways to make template classes exception safe. Unless you don't have control over all the sub-classes then you may have a problem anyway. To do this one could create typedefs in your classes that define the exceptions thrown by various template classes. This think the problem is as always tacking it on afterwards as opposed to designing it in from the start, and I think it's this overhead that's the real hurdle.
Exception specifications = rubbish, ask any Java developer over the age of 30