Some of them may repeat content, but there are simple tips for using one or the other:
No valid sentinel value
Your function may not use the watchdog value for error reporting, because all possible values are used by the function as valid responses. This can happen in different situations, primarily whole numerical algorithms. 0 and -1 are often used as special values, but some fairly common algorithms, including pow , may not be able to use those (i.e. 0^1=0 and -1^3=-1 ). Therefore, choosing the right values becomes something of an art, persistence is a problem, and users must remember the meaning of the error for each particular case.
Some APIs recognize this and (almost) never use a real return value, but rely on the return-by-reference semantics and use the return value in all functions as a status code, being either some (standard) success value or code errors specific to a particular function. CUDA, for example, has such an agreement.
Default distribution
Error codes are often referred to as “more efficient” (a comment in one of the other answers explains why this is not always the case). However, they suffer from two common problems.
- You must manually propagate the error in the call stack. This is often omitted (especially in code and book examples, which is very annoying) because it puts code with tedious and error-prone processing code.
- Erros bred at high levels because error codes between different APIs are often impossible to reconcile. Moreover, designing your own error codes that encompass the union of the error codes of all libraries is a herculian task. Therefore, in many applications you receive the message
The operation failed. instead of Ran out of disk space. .
For address (1), exceptions are propagated by default. Intentionally ignoring the error becomes apparent in the code, not hidden. For addressing (2), exceptions use a type system, not allowing you to compile a program with conflicting error values. Moreover, using a hierarchy of exception classes, you can represent “families” of related results. (Note: this is often misused and people catch Exception instead of NoMoreDiskSpace and still display the general message The operation failed. ).
Issue of consistency
Some people will recommend a mixture of both in their applications, but IMHO, this leads to a situation where both systems are used incorrectly. In these hybrid conventions, exceptions are often not caught, and error codes are not checked due to confusion. On the one hand, since exceptions are used only for exceptional situations, it is assumed that they will never occur or simply cannot be handled. On the other hand, a failure that returns an error code is considered minor and is not processed at all. And, of course, it remains for every programmer to decide whether the situation is exceptional or not, which leads to a lot of confusion between error codes for checking and exceptions for catch.
Whatever system you choose, be sure to use it to the full and be consistent in its use.