Why use an exception instead of returning an error code

Possible duplicate:
Exceptions or Error Codes

Hi,

I am looking for some recommendations on when to use v / s exceptions return values.

Thank you very much in advance.

+4
source share
8 answers

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.

+4
source

Errors are often detected at a very low level in your code, but are handled at a very high level. If you use return codes for them, you need to develop all intermediate levels to expect low-level code and distribute it until something processes it. Except in cases you only need to drop at a low level and catch at a high level (if at all). As long as your mid-tier code uses RAII, you do not need to modify any of them to propagate errors.

Therefore, I often think about the type of error and where it can be handled. If the caller is likely to handle the problem because it is expected to be a normal thing, then the return code will be great. If the error is something catastrophic (cannot allocate the necessary resource), then one cannot expect that the one who made the immediate call will handle it.

Other things to consider: Exceptions cannot be ignored; return codes can. Use an exception if it would be dangerous for the problem not to be handled.

Technically, exceptions cannot be propagated through C code. (It works on many systems, but it is not portable or guaranteed). Therefore, if you have a C library returning your C ++ code, you probably shouldn't throw an exception from the callback. Similarly for stream boundaries, etc.

+11
source

You can look at exceptions and return values ​​as two different ways of communicating between callers and callees. The return value is a good and quick way of informing parents about the materials, and the exception is a rude cousin, one that you can fire and let others know how bad he is "there."

If you write code that tries to handle each situation, you populate it with return values, error codes, etc. If you omit the handling of some situation that occurs in the log path down in the call stack and requires quick resolution for this, someone will show the MessageBox, but you can drop it and handle it at any suitable level above. Perhaps the answer to your question!

On the other hand, here are some rules that may apply:

  • use bool return values ​​for simple success / failure situations.
  • Use enum return values ​​for more complex situations.
  • use ret. values ​​for classes that know each other, for example, that serve the same purpose or are in the same module
  • use exceptions to throw away and take into account unforeseen situations. Translate system errors that previously did not reflect on some exceptions that you can handle at a higher level.

I assume that both methods will remain here. Over time, your opinion will tell you what to use in each case.

+2
source

The performance impact of exceptions is the reason that error codes are used for more frequent errors. Save exceptions for really out of the ordinary problems.

For example, in STL std::find not thrown if no match is found. But vector::push-back throws if memory is exhausted.

+1
source

C ++ exceptions are intended to be used only for exceptional errors.

They are especially useful when the error is so bad that the calling function cannot or should not handle it, for example. memory depletion. The corrected exception unwinds the stack until the first attempt blocks it (or maybe the first try block with the appropriate catch, which will make more sense). This allows you to grab an exceptional error from a deeply nested function call and ensure that the stack is cleared to a function with a try block.

All this is associated with overhead, so use return codes when you can handle a (exceptional) error inside the calling procedure.

+1
source

Along with the discussions already presented on issues related to bjskishore123 in his commentary, there is a very interesting historical background between Ned Batchelder and Joel Spolsky on this subject. You may not completely agree with Ned, but his argument is well thought out and worth reading.

+1
source

Life is simple if your function has nothing to return - it can return a success / failure code. But when your function already has a value for the return value, you need to use the "signal values" to return the error codes. Find methods that return -1, for example, use signal values. Sometimes it is almost impossible to come up with good signal values. If the function returns the next available date, then what is it returned when there is no available date? There really is no date like "-1". So this is one case where exceptions are a very useful mechanism. (It also handles functions like constructors that return nothing.)

Yes, throwing and catching an exception is a bit more expensive than checking the error code. But it cannot be forgotten, and many people find it more expressive. And, as mentioned in other answers, when there is a cascade of functions, it is inconvenient for all intermediate calls to check the return value and pass it along the chain backup.

+1
source

Use error codes when this is not unusual for something to go wrong. For example, code that opens a file or makes a network connection should not return exceptions - problems often arise.

Use exceptions when this is unusual so that something goes wrong - failure is truly exceptional.

So this can be simplified:

  • Use error codes most of the time.
0
source

All Articles