I was wondering if there is some compiler parameter, preferably in gcc (g++) which treats the lack of try/catch blocks as errors. This is the standard behavior in java and I was alway fond of it.
Since checked exceptions in Java rely on the throw signature, you can read why you will not want to use throw function signatures in C++ in this question on SO.
Well, using exception specifications is generally a bad idea: http://cplusplus.co.il/2009/10/06/exception-specifications/
And if not using these, the compiler basically has no way of knowing which exception may be thrown, so there's no way to do that.
What you could do, is provide your own implementation of std::terminate (by invoking std::set_terminate()) and handle uncaught exceptions there.
One thing you can do in C++ with exceptions is use exception specifications on your functions. That doesn't actively prevent non-listed exceptions from being thrown from that function, but it makes them errors (and maps them all to the predefined unexpected().
So int f() throw (); is C++ for "treat any exception being raised from function f as an error".
Related
Introduction:
In Java, if you do not catch an exception, your code doesn't even compile, and the compiler crashes on unhandled exception.
Question:
Is there a way to tell GCC to be "strict" as Java in this case, and to raise an error or at least a warning on unhandled exception?
If not - are there IDEs (for Unix, please) that can highlight such cases as a warning?
It is not possible in C++. Exception specification is a part of a function declaration but not a part of its type. Any indirect call (via pointer or virtual call) just completely wipes any information about exceptions.
Exception specifications are deprecated anyway in C++11 in favour of noexcept, so it is unlikely any compiler would bother to enhance this language feature.
The only guarantee you can put on a C++ function is that it never throws an exception at all:
void f() noexcept;
However, this will terminate the program at runtime when an exception is thrown. It's not verified at compile-time.
If you want to guarantee that an error is handled, the closest you can get is returning a value of a type that wraps boost::variant<OK, Error> with a member function that takes two callbacks: a callback for the OK case and one for the Error case.
You can ALWAYS use:
int main()
{
try {
... your usual main ...
}
catch(...)
{
std::cerr << "Unhandled exception caught" << std::endl;
}
}
However, that is a fairly poor solution.
Unfortunately, the nature of C++ makes it very hard to catch the situation where something throws an exception and it's not handled, since just about everything has the potential to throw exceptions. I can only think of code-review - perhaps code analyzing tools, such as that built around CLANG will have the capability of doing this, but it probably won't be 100% accurate. In fact, I'm not even sure that the Clang Analyzer fully understands throw/try/catch currently, as it seems to not catch some fairly fundamental errors http://clang-analyzer.llvm.org/potential_checkers.html (see the "exceptions" heading).
First, your statement concerning Java is false; only certain
types of exceptions prevent the code from compiling. And for
the most part, those types of exceptions correspond to things
that are better handled by return codes. Exceptions are normally
only an appropriate solution when propagating an error through
a large number of functions, and you don't want to have to add
exception specifications for all of those functions.
That's really why Java makes its distinctions: exceptions that
derive from java.lang.Error should usually be crashes
(assertion failures and the like in C++); and exceptions that
derive from java.lang.RuntimeException should be exceptions in
C++. Neither are checked in Java, either, because it isn't
reasonable to have every function declare that it might throw
one of them.
As for the rest, the exceptions which you want to catch
immediately in the calling code, they are generally best handled
by return codes, rather than exceptions; Java may use exceptions
here because it has no out arguments, which can make using
return codes more awkward. Of course, in C++, you can also
silently ignore return codes, which is a drawback (but
historical reasons, etc.). But the real issue is the contract,
which is far more complex than function f might throw/return x;
it's more along the lines of "function f will throw/return x,
if condition c is met". And I know of no language which has
a means of enforcing that. In C++ (and for checked exceptions
in Java), exception specifications are more along the lines of
"function f will not throw anything but x". Which is generally
not very useful, unless "x" means all exceptions. In order to
write really robust code, you need a few functions which are
guaranteed never to throw. Interestingly enough, you can
specify this in C++, both pre-C++11 (throw()) and post
(noexcept); you cannot in Java, because you can't specify that
a function won't throw a java.lang.RuntimeError.
(Or a java.lang.Error, but that's less of an issue, since if
you get one of those, you're application is hosed anyway. Just
how are you expected to recover from
java.lang.VirtualMachineError? And of course, you can't
really expect to be able to recover from a segment violation in
C++ either. Although... java.lang.OutOfMemoryError derives
from java.lang.VirtualMachineError; although not easy, and not
always applicable, I've written C++ code which successfully
recovered from std::bad_alloc.)
I just read that in the C++11 standard revision, exception specifications were deprecated. I previously thought specifying what your functions may throw is good practice, but apparently, not so.
After reading Herb Stutter's well-cited article, I cannot help but wonder: why on earth are exception specifications implemented the way they are, and why has the committee decided to deprecate them instead of having them checked at compile-time? Why would a compiler even allow an exception to be thrown which doesn't appear in the function definition? To me, this all sounds like saying "You probably shouldn't specify your function return type, because when you specify int f(), but return 3.5; inside of it, your program will likely crash." (i. e., where is the conceptual difference from strong typing?)
(For the lack of exception specification support in typedefs, given that template syntax is probably Turing-complete, implementing this sounds easy enough.)
The original reason was that it was deemed impossible to
reliably check given the body of existing code, and the fact
that no specifier means anything can throw. Which means that
if static checking was in force, the following code wouldn't
compile:
double
safeSquareRoot( double d ) throw()
{
return d > 0.0 ? sqrt( d ) : 0.0;
}
Also, the purpose of exceptions are to report errors over
a great distance, which means that the intermediate functions
shouldn't know what the functions they call might throw.
Requiring exception specifiers on them would break
encapsulation.
The only real case where a function needs to know about the
exceptions that might occur is to know what exceptions cannot
occur. In particular, it is impossible to write thread safe code
unless you can be guaranteed that some functions will never
throw. Even here, static checking isn't acceptable, for the
reasons explained above, so the exception specification is
designed to work more like an assertion that you cannot
disactivate: when you write throw(), you get more or less the
equivalent of an assertion failure if the function is terminated
by an exception.
The situation in Java is somewhat different. In Java,
there are no real out parameters, which means that if you can't
use return codes if the function also has a return value. The
result is that exceptions are used in a lot of cases where
a return code would be preferable. And these, you do have to
know about, and handle immediately. For things that should
really be exceptions, Java has java.lang.RuntimeException
(which isn't checked, statically or otherwise). And it has no
way of saying that a function cannot ever throw an exception; it
also uses unchecked exceptions (called Error) in cases where
aborting the program would be more appropriate.
If the function f() throw(int) called the function g() throw(int, double) what would happen?
A compile time check would prevent your function from calling any other function with a less strict throw specifier which would be a huge pain.
Is there any way in C++ to get a compile-time error or warning if an exception is unhandled? For example, consider this Java code snippet:
public void f()
{
g(); // <-- Java compiler reports "Unhandled exception" error here.
}
public void g() throws Exception
{
}
Can g++ or MSVC do something similar? Or is there any external code parsing tool which can do this? I suppose one could programmatically extend the C++ parser of Eclipse CDT to achieve this, but... are there easier solutions?
Simply, no. C++ exception specifications have a different meaning to Java's exception specifications and they are now deprecated so you should consider avoiding them if possible.
In C++, the checks requested by exception specification are enforced only at runtime. In C++, if a function violates its exception specification the the "unexpected" handler is called. It is not a compile time error to call a function that can potentially throw an arbitrary exception from a function with an exception specification.
ISO/IEC 14882:2011 15.4 [except.spec] / 11:
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.
Short answer: no. There are no checked exceptions in C++. You can try to use an external tool, but TBH I've never seen anyone do that. Just document the interfaces properly.
I recently saw that the boost program_options library throws a logic_error if the command-line input was un-parsable. That challenged my assumptions about logic_error vs. runtime_error.
I assumed that logic errors (logic_error and its derived classes) were problems that resulted from internal failures to adhere to program invariants, often in the form of illegal arguments to internal API's. In that sense they are largely equivalent to ASSERT's, but meant to be used in released code (unlike ASSERT's which are not usually compiled into released code.) They are useful in situations where it is infeasible to integrate separate software components in debug/test builds or the consequences of a failure are such that it is important to give runtime feedback about the invalid invariant condition to the user.
Similarly, I thought that runtime_errors resulted exclusively from runtime conditions outside of the control of the programmer: I/O errors, invalid user input, etc.
However, program_options is obviously heavily (primarily?) used as a means of parsing end-user input, so under my mental model it certainly should throw a runtime_error in the case of bad input.
Where am I going wrong? Do you agree with the boost model of exception typing?
In this case, I think (at least for the most part) you're right and it's wrong. The standard describes logic_error as:
The class logic_error defines the type of objects thrown as exceptions to report errors presumably detectable before the program executes, such as violations of logical preconditions or class invariants.
A command line argument that can't be parsed doesn't seem to fit that very well.
By contrast, it describes runtime_error as:
The class runtime_error defines the type of objects thrown as exceptions to report errors presumably detectable only when the program executes.
That seems to be a better fit.
From a pure standard point of view, you are right. program_options should throw classes derived from either runtime_error or logic_error depending on whether the error is runtime or logical. (I did not review the current code to determine such idea classification for current exceptions).
From a practical standpoint, I have yet to see C++ code that makes useful decisions based on whether exception is logic_error or runtime_error. After all, the only reason you would throw a logic_error as opposed to letting assert file is if you want to try recover somehow, and that's not different from recovery from a runtime error. Personally, I view logic_error vs. runtime_error the same way as checked exceptions in Java -- theoretically nice, but not useful in practice. Which means, that maybe, I'll just make program_options::error derive from exception. That is, when I'll find that 'spare time' everybody keeps talking about.
The current draft of the C++0x Standard says (clause 19.2):
1) In the error model reflected in
these classes (i.e. the exception types), errors are divided into
two broad categories: logic errors and
runtime errors.
2) The distinguishing characteristic
of logic errors is that they are due
to errors in the internal logic of the
program. In theory, they are
preventable.
3) By contrast, runtime errors are due
to events beyond the scope of the
program. They cannot be easily
predicted in advance.
Together with the quotes cited in one of the other answers this explains why Boost.ProgramOptions throws a std::logic_error for preventable errors caused by an 'error presumably detectable before the program executes'.
The user could verify that the file exists, run the program, and suddenly learn that the file has been deleted. That's why an I/O problem is always a runtime_error. Stateful problems are runtime_errors, even if the caller could have checked, since another thread could cause the problem.
logic_error is when the arguments to a function are wrong. It is only for things which could have been caught earlier with stronger type-checking.
So, "missing file" is a runtime_error, but "improperly formatted filename" is a logic_error.
Technically, a logical error within a function is a logic_error too, but if you're smart enough to test for it inside your own function, you should be smart enough to prevent it in the first place.
IMO,
std::logic_error is thrown by a user C++ program logic intentionally. Predicted by a user program.
std::runtime_error is thrown by a C++ runtime (or core part of the langauge…) to abstract lower level errors. Just happens without any intention without involving of any user code.
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!
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.
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.
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.
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.
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++.
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.