views:

816

answers:

6

C++ provides a syntax for checked exceptions, for example:

void G() throw(Exception);
void f() throw();

However, the Visual C++ compiler doesn't check them; the throw flag is simply ignored. In my opinion, this renders the exception feature unusable. So my question is: is there a way to make the compiler check whether exceptions are correctly caught/rethrown? For example a Visual C++ plugin or a different C++ compiler.

PS. I want the compiler to check whether exceptions are correctly caught, otherwise you end up in a situation where you have to put a catch around every single function call you make, even if they explicitly state they won't throw anything.

Update: the Visual C++ compiler does show a warning when throwing in a function marked with throw(). This is great, but regrettably, the warning doesn't show up when you call a subroutine that might throw. For example:

void f() throw(int) { throw int(13); }
void h() throw() { g(); } //no warning here!
+11  A: 

Have a look at this:

http://www.gotw.ca/publications/mill22.htm

basically exception specifications are unworkable/unusable but that doesn't make exceptions unworkable.

As for your question, there is no way to get the compiler to check that every type thrown is caught somewhere higher in the code, I expect compilation units make this difficult and it's impossible to do it for code intended to be used in a library (where the top level is not available at compile time). If you want to be sure everything is caught then stick a catch(...) at the very top of you code.

Patrick
A: 

I cannot check this for lack of a MSVC installation, but are you really sure the compiler ignores the throw() specification?

This MSDN page suggests that Microsoft is aware of throw() and expects their compiler to handle it correctly. Well, almost, see the note about how they depart from the ANSI/ISO standard in some details.

Edit: In practice, though, I agree with Patrick: Exception specifications are mostly useless.

DevSolar
+5  A: 

Because the standard says so. The exception declaration doesn't mean that no other exception will be thrown. It means that if an undeclared exception is thrown, there will be called a special global function called unexpected(), which by default terminates the program. Generally declaring exceptions in functions is discouraged (maybe except for empty exception list) as the standard behaviour is not very helpful.

Tadeusz Kopec
+11  A: 

Exception specifications are pretty useless in C++.

It's not enforced that no other exceptions will be thrown, but merely that the global function unexpected() will be called (which can be set)

Using exception specifications mainly boils down to deluding yourself (or your peers) into some false sense of security. Better to simply not bother.

Pieter
"Impossible" is a pretty strong claim. Why is enforcement of exception specifications impossible with templates?
Rob Kennedy
thinking about it, you're right of course, don't know where I got that, removed the paragraph
Pieter
+3  A: 

To detect prior to runtime cases such as ...

extern void f() throw (class Mystery);
void g() throw() { 
    f() ; 
}

... you need static analysis. Yes, the compiler is doing plenty of static analysis, but because the standard is "raise std::unexpected if the throw doesn't match," and it is perfectly legal to write a routine that throws an object that does not match the specifier, the compiler implementers neither warn nor remark.

Static analysis tools that claim to provide warning service include Gimpel Software's lint for C++ ...

1560 Uncaught exception 'Name' not on throw-list for function 'Symbol'

and, according to this answer to a prior question, QA C++.

Thomas L Holaday
+5  A: 

What's funny is that Java has checked exceptions, and Java programmers hate those too.

Exception specifications in C++ are useless for 3 reasons:

1. C++ exception specifications inhibit optimization.

With the exception possibly of throw(), compilers insert extra code to check that when you throw an exception, it matches the exception specification of functions during a stack unwind. Way to make your program slower.

2. C++ exception specifications are not compiler-enforced

As far as your compiler is concerned, the following is syntactically correct:

void AStupidFunction() throw()
{
    throw 42;
}

What's worse, nothing useful happens if you violate an exception specification. Your program just terminates!

3. C++ exception specifications are part of a function's signature.

If you have a base class with a virtual function and try to override it, the exception specifications must match exactly. So, you'd better plan ahead, and it's still a pain.

struct A
{
    virtual int value() const throw() {return 10;}
}

struct B : public A
{
    virtual int value() const {return functionThatCanThrow();} // ERROR!
}

Exception specifications give you these problems, and the gain for using them is minimal. In contrast, if you avoid exception specifications altogether, coding is easier and you avoid this stuff.

rlbond
Nice answer! Thanks.
Dimitri C.