C++ exception specifications are evil

When I began to program in C++ I was already experienced in C and had written some code in Java. After writing few thousands lines of code in this language I felt comfortable with all of it's goodies like templates, inheritance, operator overloading and (I thought so) exceptions. But I made at least one mistake: I used exception specifications. My intention was to use them as in Java: tell the compiler that this method throws specific exceptions so it can use this information to optimize code and tell me when I'm throwing/catching wrong exceptions. A great surprise was that in practice in most cases writing exception specifications slows the code and introduces bugs!

Before you read the rest of this article, keep in mind that despite of most information here are generally true with C++ I'm writing this specifically about g++ and Linux, so things may not work as described when you use a different environment. All examples are presented using g++ 4.3.2 on Ubuntu.

Exception specifications don't do what then should (like in Java)


After reading a C++ book that just describes the syntax of the language and (what's worst) after using exceptions in Java you might think that specifying exceptions that a method throws prevents you in some way of making mistakes like throwing an exception that is not handled and you might even think that the compiler will issue a warning when you violate the specification. You are very mistaken. Just see this code:

  1. class A
  2. {
  3. };
  4.  
  5. class B
  6. {
  7. };
  8.  
  9. void f() throw (A)
  10. {
  11. throw B();
  12. };
  13.  
  14. int main ()
  15. {
  16. try {
  17. f ();
  18. }
  19. catch (A &e) {
  20. cout << "Exception A\n";
  21. }
  22. catch (B &e) {
  23. cout << "Exception B\n";
  24. }
  25. catch (C &e) {
  26. cout << "Exception C\n";
  27. }
  28.  
  29. return 0;
  30. }

Let's try compile it with g++ -Wall -W -o test test.cpp. The effect? it does compile cleanly without any warning! This example shows us two important facts about exception specifications:

They don't prevent from throwing exception not listed in the specification


You might think an exception specification is a good form of documentation integrated in code: you look at the header file and see that a method you want to use throws only exception A and want to handle that. As you can see it doesn't work this way. There is no switch in g++ to do that, it's not behaviour of a particular g++ version, it just works this way. The specification gives a false feeling that you know which exceptions are thrown.

They are not used to verify exception handling


The compiler didn't warned us that we are trying to catch exception C even that it's obvious from the specification and the function body that this exception is not thrown. Worse: if you run this example it will crash with terminate called after throwing an instance of 'B' message, so catching the B exception doesn't work. If you remove the specification the example will work properly.

Performance


You might think that there is a performance gain when using exception specifications because it seems that the compiler can optimize the code because it knows what to expect from a method call. On my system compiling the example gives a 10142 bytes file. After removing the specification the result file is 10084, so it's actually smaller! Why? Because calling such function requires in fact a bit more code for calling unexpected exception handler (result was seen when running the original example), without the specification the exception is just passed to the lower frame.

When to write exception specifications?


From the experience of boost authors (see references) the only place worth specifying exceptions when you have a method that is not inlined and it doesn't throw an exception, so using throw() there might increase performance. The other place to write exception list is... a comment. It's good to have a documentation in code in form of comments that tells you what exceptions a function throws, but you must remember these might be not all of them just because a method calls other methods.

Conclusion


When I discovered that using exception specification doesn't gain you anything with g++ I started to search for a static code analyse tool that will verify use of exceptions based on specifications but hasn't found anything (at least any free tool), so it makes this language construction even more useless.

So why they exist? Handling exception specifications in C++ is dynamic. This is an opposite approach in to the static enforcement in Java where they are checked at compile time. The intention was to have the unexpected handler called to take some action like throwing a different exception. In practice it's rarely seen that unexpected does something more than terminating the program with some error message because programmer's possibilities when writing custom handler are very limited.

References


More information about this topic can be found in:

Comments

Very Guilty

I'm very guilty of using these.. The rational for not using them is very sound though. Thank you!

just a thought

well, i see what you wanted to show-exception specifications can be pain in the arse, but neither one c++ compiler is in obligation to detect misuse during compilation: (quote from 15.4/10 of ISO/IEC 14882) An implementation shall not reject an expression merely because when executed it throws or might throw an exception that the containing function does not allow i tend to use them as a warning to libary user or to unify exception handling (use class derived from std::exception) without any hopes of optimization for example