This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
design by contract tests by assert or by exception?
Is there a rule of thumb to follow when deciding to use exceptions instead of asserts (or vice versa). Right now I do only throw if it's something I think will happen during runtime on the user side (like a socket or file error). Almost everything else I use asserts.
Also, if I were to throw an assert, what is a nice standard object to throw? If I recall correctly there is std::logic_error, but is that not a good object to throw? What would I throw for a missing file or unexpected input (such as from the command line instead of a frontend app)?
My rule of thumb:
Exceptions are used for run-time error conditions (IO errors, out of memory, can't get a database connection, etc.).
Assertions are used for coding errors (this method doesn't accept nulls, and the developer passed one anyway).
For libraries with public classes, throw exceptions on the public methods (because it makes sense to do so). Assertions are used to catch YOUR mistakes, not theirs.
EDIT: This may not be entirely clear, due to the null value example. My point is that you use assertions (as others have pointed out) for conditions that should NEVER happen, for conditions that should NEVER make it into production code. These conditions absolutely must fail during unit testing or QA testing.
Assert the stuff that you know cannot happen (i.e. if it happens, it's your fault for being incompetent).
Raise exceptional situations which are not treated by the regular control flow of the program.
You use exceptions for exceptional situations. For example an out of memory situation or a network failure.
You use assert to ascertain that a cetain precondition is met. For example a pointer is not NULL or an integer is within a certain range.
I use asserts for things that should never happen, yet do. The sort of thing that when it happens, the developer needs to revisit incorrect assumptions.
I use exceptions for everything else.
In reusable code, I prefer an exception because it gives the caller a choice of handling or not handling the problem. Just try catching and handling an assert!
Assert is a means to verify that the program is in a possible state. If a function returns -1 when it should only return positive integers, and you have an assert that verifies that, your program should stop because it puts your program in a dangerous state.
As a general rule, I throw exceptions from:
public functions of a package to catch programming errors.
internal functions to report system errors or pass-through sub-system errors.
where I use asserts only internally to catch implementation mistakes.
Related
Say I'm using a library that has a function to_int that takes a string parameter. This function returns an int if the string is a character representation of a number, e.g "23" would return 23. If the string isn't a number it throws an std::runtime_error. Would it be better to:
if(is_all_digits(str))
x = to_int(str);
else
output("not an int, idiot. Try again");
Or
try
{
x = to_int(str);
}
catch(...)
{
output("not an int, idiot. Try again");
}
There are several different error handling techniques and each have advantages and disadvantages.
Lets consider a function getAllElements() which gets a container with some elements.
Now this may produce an error (database connection or whatever). You now have the options
Errorcode getAllElements(std::vector<...> & cont);
or
std::vector<...> getAllElements(); //throws exceptions
It is kind of a general design question usually and depends on circumstances. I prefer the one with the exceptions for multiple reasons. I can just assign and don't need a predetermined container
auto elements = getAllElements();
The next thing is where will you handle your errors? If you handle them like 5 functions above in the stack you have to check for the error-code every time and just give it to the next function. An exception will automatically propagate until someone catches it and is able to deal with it.
Exceptions though have some disadvantage. They cause a bigger binary and is slower when an exception gets thrown. In game development usually no exceptions are used because of that ( Listen to this for more info on that: http://cppcast.com/2016/10/guy-davidson/ they talk about why not using exceptions. I don't have the timestamp currently though. )
Also exceptions should be used in exceptional cases. Errors you cannot deal with immediately and have to be dealt with somewhere higher.
So if you don't need high performance / a small binary I would suggest using exceptions where they are useful. They can result in typing less code (like checking return codes) which can result in less places for introducing bugs.
Here is also a good discussion on error handling mechanisms from CppCon 2016:
CppCon 2016: Patrice Roy “The Exception Situation"
There is no single answer to this question, as it depends on how the program as a whole can deal with bad input, and whether it can sensibly recover when errors are detected (regardless of whether those errors are reported using return codes or by throwing exceptions).
Can every function which calls to_int() recover from bad input immediately? If not, it is better to allow an exception to be thrown .... so it unwinds the stack until there is some caller (with a try/catch block) that can actually recover from the error.
What if you have numerous functions that call to_int(), do you want to do the check in every one? If so, this results in a lot of code duplication.
What if you have some function that calls to_int() which can recover immediately from the error and some others that cannot?
What if you want to report an error to the caller (e.g. to allow something more substantial than writing an error string)?
What is there is no is_all_digits() function? If there is not, what if you implement it in a way that misses some errors that to_int() will detect? Then you have the worst of both worlds - doing the error checking in an attempt to prevent an exception being thrown, but then the function throwing an exception anyway. For example, there might be some global setting that causes to_int() to only accept octal digits (in range 0 to 7), but your is_all_digits() function deems all decimal digits to be valid.
More generally, the real need is to define an error handling strategy that works for your program as a whole. Trying to decide, based on usage of a single function, between throwing exceptions or not throwing exceptions, is completely missing the point.
If it makes sense for your program to report errors using exceptions (e.g. with a single centralised try/catch block in main() so all errors propagate up the call stack so main() implements the recovery globally) then throw exceptions. If it makes sense for every function in your program to detect errors and silently deal with them on the spot, then avoid exceptions.
What I'm advocating is allow the dog (your program) to wag the tail (low level decisions on how to handle errors). Your question is essentially asking if it is appropriate to allow the tail to wag the dog.
If the caught exception is really specific than you can use a specific try catch (using a generic try catch is not a good idea since you are hiding a bunch of other possible errors)
Generically speaking my preference is to check the string before passing it to the function.
When you are using a library or an API you want it to prevent you from bad usages and other mistakes.
This is the role of your function to control the integrity of the given parameters, and to throw an exception.
Note that you can also use assertions when developing your code, and then disable it for binary production.
How to handle failed methods:
using exceptions
making the methods return bool
The first approach is when something goes wrong to throw an exception.
But the problematic code needs to be placed in a try block,
and then you need to write the catch block.
The second approach you need to check the return value from
the method, and then do something.
So basically isn't it the same mechanism? You have two parts:
detecting that something goes wrong and then doing something about it.
So does it matter then which approach I use?
The main benefit with exceptions is that they are non-local. You can catch an exception several invocation layers away from where it was thrown. That way, code in between doesn't have to care about exceptions (except ensuring proper cleanup during unwinding, i.e. being exception safe), which makes it less likely that an exceptional situation gets forgotten. But this benefit comes at a price: stack unwinding is more complicated than simply returning a value. In terms of performance, the return value approach is usually simpler.
So I'd use these to choose: if for some reason the only reasonable place to deal with a problem is directly at the location where the function was called, and if you are fairly certain that every caller will include some kind of error handling code in any case, and is not likely to forget doing so, then a return value would be best. Otherwise, I'd go for an exception.
Basically you can reach the same behavior with both approaches, but Exception can give 2 added values:
1) You don't have to handle the error in the exact calling method, it can be anywhere up the call stack. this remove the if(!doSomthing()) return false; from the code when you just want to pass the error up.
2) It allow you to write a block of code, under one try and handle all the errors under it in one catch block.
There is no simple answer. For instance, here is the conclusion of the article C++ Exceptions: Pros and Cons
There is no simple answer to the "exceptions or error codes" question. The decision needs to be made based on a specific situation that a development team faces. Some rough guidelines may be:
If you have a good development process and code standards that are actually being followed, if you are writing modern-style C++ code that relies on RAII to clean up resources for you, if your code base is modular, using exceptions may be a good idea.
If you are working with code that was not written with exception safety in mind, if you feel there is a lack of discipline in your development team, or if you are developing hard real-time systems, you should probably not use exceptions.
My personal rule is to raise exception only when something exceptional occurs, ie when the problem may not have appeared at all. Otherwise I use return value (most of the time).
For example, when searching for a file that MUST exists, not finding it raises an exception. But if the file may or may not exists, not finding it is not exceptional so no need for an exception.
There's no answer for all situations. Both approaches have strengths and weaknesses:
Exceptions:
are slightly more verbose to handle locally
can simply be ignored if the error can't be handled locally
can carry as much information as you like about the error, both statically (in the exception type) and dynamically (in the thrown object)
require a handler somewhere to avoid terminating the program
may have more runtime overhead (but may have less when nothing is thrown, depending on how they're implemented)
require the code to be exception safe
Return values:
must be manually passed up the stack if not handled locally: prone to bugs if you forget
have a fixed type, limiting how much information they can carry (although you could return a pointer to a polymorphic type, and deal with the associated lifetime management issues)
are awkward to use if the function also needs to return something on success
There are two main differences: (a) it is easier for the calling code to just silently ignore the boolean status code. (b) Exceptions provide more context than mere false. You can distinguish business-logic errors from I/O errors from input validation errors etc.
I prefer bools. I'd say its personal preference.
I have found it easier to read.
I like very much the assert behaviour for testing invariants and pre-conditions in my code. I use it a lot. But now I am developing a library (C++) and I like the client (the programmer who uses the library) to know when he violates the precondition. I think is easier to see the application crashes and fix the problem than just throwing in a undefined behaviour.
I could just use assert in this situation, but when my library is ready a release build will disable the assert macro. I know I can keep it but I'm not sure I want to because there is a lot of internal asserts don't need being tested in release build.
An instance:
Some state machine has a maximum number of states that can be added. The limit is setted by the client in the constructor. Then, the client calls the method addState to add specific states, but of course, he can't add more states than he said initially.
Should I:
Just ignore states after the limit and, probably, start a state machine with undefined behaviour (at least to client perspective)?
Keep assertions alive and put an assertion at that point?
Throw an exception (some std::logic_error, I presume)?
Just print a message to stderr and abort the program?
I don't like 1. very much. The idea is tell the client what is he doing wrong.
Is this a situation to throw a logical error exception?
Is there another, better possibility?
Thanks.
Definitely, if a problem is "detectable", you should do something to inform the "user" of the error (some things are very hard to identify that it's gone wrong)
You use assert when the programmer does something directly wrong, and that is unlikely to happen in "normal use" of the code. E.g. if you have a pointer parameter that mustn't be NULL, doing assert(ptr != NULL) would be a sensible thing, likewise if you have an int that is a count of something, it probably shouldn't be negative (but then it should probably be unsigned?). These type of things don't necessarily need to be that clearly documented - just that the precondition "ptr must not be NULL" or "count should not be negative".
You use exceptions for something that MAY happen in normal running conditions, but really shouldn't. Such as running out of memory, or the "user" trying to add too many things to something that they had a reason to give a reasonable size in the first place. Exceptions should be clearly documented by the description of the function - "If you try to add more states than you have reserved space for, the exception x will be thrown".
I personally would think that a "custom" exception would make more sense than std::logic_error. In this case, perhaps too_many_states? The more distinct your exception is, the easier it is to determine where it came from and what it means. Nothing worse than getting some "generic" exception and not knowing how you ended up there - and when you search for it, there are hundreds of places it could have come from...
I have realized, after some reading, that in C++ the exceptions specification is considered a bad thing:
int f() throw(A, B); // bad because a lot of reasons
(some references: 1, 2, etc.)
What I have not understood is how to replace it. How can I tell to the f()'s caller that he must catch an exception?
How about
//throws: A if something is wrong
// B if something else is wrong
int f();
You don't. Not saying anything means it can throw anything.
I assume you have some Java background to ask this question. Compile-time exception checking was a Java experiment that failed. That's why you don't see it anywhere else.
The general rule for exception handling is: handle it where you can. This usually boils down to a try-catch at some very high level, where you basically tell the user whatever he was trying to do failed. It is very rare to be able to recover from an exception and continue the operation.
You should, of course, provide documentation what exceptions your function throws. I don't consider this to be a replacement for the throw specification (its purpose is very different). You should document the exceptions that your function throws and can be handled meaningfully by the caller, whereas the throw specification has to list any exceptions that may come out of this function (and the functions it calls).
You could replace it with an automated documentation tool.
Such tools often have the ability to nicely format which exceptions a method will throw, like the doxygen \exception command (or \throw or \throws). Assuming users of your code read documentation, they would be able to find out what exceptions to catch.
/**
* #exception A
* #exception B
*/
int f();
See this question for more useful info: How to document all exceptions a function might throw?
How can I tell to the f()'s caller that he must catch an exception?
That you think the caller must catch an exception indicates that there might be something wrong with your design. Are you using exceptions to signal a non-exceptional circumstance such as end of file?
Mandating the immediate callers to catch all possible exceptions is bad design. Example: The push_back member functions of the standard library containers allocate memory, which can fail. The designers of the library did not expect callers to wrap each and every push_back in a try/catch block. It doesn't make sense. Doing so would make the code much uglier, much harder to test. Besides, how would you recover from an out of memory condition? Handling this once, at a high level, is about all you can do.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Exceptions or error codes
Hi,
I am looking for some guidelines on when to use return values v/s exceptions.
Many thanks in advance.
Errors are often detected at a very low level in your code, but handled at a very high level. If you use return codes for these, you have to design all the intermediate levels to expect the low level code and propagate it up until something handles it. With exceptions, you only need to throw at the low level, and catch at the high level (if at all). As long as your intermediate level code uses RAII, you don't have to change any of that to do the error propagation.
So I often think about the type of error and where it's likely to be handled. If the caller is likely to handle the problem, because it's expected to be a common thing, then a return code is great. If the error is something catastrophic (cannot allocate a necessary resource), then the immediate caller cannot be expected to handle it.
Other things to consider: Exceptions cannot be ignored, return codes can. Use an exception when it would be dangerous for the problem to go unhandled.
Technically, exceptions cannot propagate back up through C code. (It works on many systems, but it's not portable nor guaranteed.) So if you've got a C library calling back into your C++ code, you probably shouldn't throw an exception from the callback. Likewise for thread boundaries, etc.
Some of this might repeat content, but here are simple hints as to use one or the other:
No proper sentinel value
Your function might not be able to use a sentinel value to signal an error because all possible values are used by the function as valid answers. This may happen in different situations, most notably integer numerical algorithms. 0 and -1 are often used as special values but some fairly common algorithms, including pow might not be able to use those (i.e. 0^1=0 and -1^3=-1). Therefore, choosing proper values becomes somewhat of an art, consistancy is an issue and users have to remember the error value for each and every special case.
Some APIs recognize this and (almost) never use a real return value but consistently rely on return-by-reference semantics and use the return value in all functions as a status code, being either some (standard) "success" value, or a function-specific error code. CUDA, for instance, has such a convention.
Propagate by default
Error codes are often stated to be "more efficient" (a comment in one of the other answers explains why this is not necessarily true). However, they suffer from 2 common problems.
You have to manually propagate the error up the call stack. This is often omitted (especially in example code and books, which is very irritating) because it litters the code with tiresome and error-prone handling code.
Erros are diluted at high levels because error codes between different APIs are often impossible to concialiate. Moreover, designing you own error codes that cover the union of all libraries' error codes is a herculian task.This is why, in many applications, you get an The operation failed. message instead of Ran out of disk space..
To address (1), exceptions are propagated by default. Intentionally ignoring an error becomes obvious in the code, instead of hidden. To address (2), exceptions use type system, preventing you from compiling a program that has conflicting error "values". Morever, using an exception class hierarchy you can represent "families" of related results. (Note: this is often misused, and people catch Exception instead of NoMoreDiskSpace and still display the generic The operation failed. message).
A matter of consistancy
Some people will recommend a mixture of both in their applications, but IMHO, this leads to a situation where both the systems are mis-used. In these hybrid conventions, exceptions are often not caught and error-codes not checked because of confusion. On one hand, because exceptions are used only for exceptional situations, it is assumed they will never occur, or simply cannot be handled. On the other hand, a failure returning an error code is assumed to be minor and is not handled at all. And of course it is left up to each programmer to decide whether an situation is exceptional or not, leading to lots of confusion between what error codes to check and what exceptions to catch.
Which ever system you choose, be sure to use it at its full strength, and be consistent about its use.
You can look at exceptions and return values as two different methods of communication between callers and callee's. Return value being nice and quick way of informing parent about stuff, and exception being the rude cousin, one that you can fire and let others know how bad it is 'down there'.
If you write code that tries to handle every situation, you'll fill it with return values, error codes etc. If you omit handling some situation that occurs log way down on the call stack, and want quick resolution for this - someone will show MessageBox at this point - but you can throw, and handle it at any appropriate level above. Maybe that's the answer to your question!
On second thought, here are some rules that might apply:
use bool return values for simple success/fail situations
use enum return values for somewhat more complex situations
use ret. values for classes that know of each other, for example that serve same purpose or are in same module
use exceptions to throw far and account for unforeseen situations. Translate system errors that are not previously thought of to some exception of yours that you can handle on some higher level
I guess that both methods are here to stay. With time, your judgement will say which to use on each occasion.
There is a performance impact when exceptions are thrown that is the reason why error codes are used for more frequent error conditions. Save exceptions for truly out of the ordinary problems.
For example - in the STL, std::find does not throw if no match is located. But vector::push-back throws if memory is exhausted.
C++ exceptions are supposed to be used only for exceptional errors.
They are particularly useful for when an error is so bad that the calling function can't, or indeed shouldn't, handle it, e.g. a memory exhaustion. A thrown exception unwinds the stack until the first try block that it sees (or maybe the first try block with an appropriate catch, which would make more sense). This allows you to catch an exceptional error from a deeply nested function call, and be guaranteed that the stack is clean down to the function with the try block.
This all comes with overhead though, so use return codes when you can handle the (unexceptional) error inside the calling routine.
Along with the discussions already presented in the questions linked to by bjskishore123 in his comment, there is a very interesting historical back-and-forth between Ned Batchelder and Joel Spolsky on the subject. You may not entirely agree with Ned, but his argument is well thought out and worth a read.
Life is simple if your function has nothing to return - it can return a success/fail code. But when your function already has a meaning to its return value then you need to use "signal values" to return error codes. Find methods that return -1, for example, are using signal values. Sometimes it's almost impossible to come up with good signal values. If a function returns the next available date, what shoud it return when there is no available date? There's really no "-1" type date. So this is one case where exceptions are a very helpful mechanism. (This also handles functions like constructors that don't return anything.)
Yes, throwing and catching an exception is slightly more expensive than checking an error code. But it can't be forgotten and many people find it more expressive. And, as mentioned in other answers, when there is a cascade of function calls it's awkward to have all the intermediary calls check the return value and pass it along back up the chain.
Use error codes when it is not unusual for something to go wrong. For example, code that opens a file or makes a network connection should not return exceptions - it is very common for there to be problems.
Use exceptions when it is unusual for something to go wrong - the failure is truly exceptional.
So, that can be simplified to:
Use error codes most of the time.