views:

152

answers:

3

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?

A: 

There is absolutely no standard that says what exception type you must throw when. IMHO, this means that complex exception hierarchies are a bad thing - I prefer to throw one single type, derived from std::exception.

anon
+5  A: 

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.

Jerry Coffin
A: 

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'.

hkaiser
By your logic, if the user passed in an argument containing a path to a non-existent file, the application should throw a logic error in response to the file-not-found runtime error since the argument to the application, created before the application started, was provably incorrect. I don't buy that.
David Gladfelter
Well, actually it's not my logic. I gave you quotes from the Standard. Obviously, there is no sharp destinction possible between both types of errors, and wrong user input is one of those 'gray zones'.
hkaiser