开发者

Confused about std::runtime_error vs. std::logic_error

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 release开发者_如何学JAVAd 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜