Should I add exception-handling to existing code base? - c++

I'd like to know the advantages and disadvantages of adding exception-handling to existing code.
I work on a SDK that controls h/w cards in a Windows environment.
The SDK is made of more than 100 DLLs that interact with each other. Our existing code base probably contains 100 000s (if not 1 000 000s) of lines of code. Our modules are also heavily multi-threaded.
We link with the proper library so that we use nothrow new (lic.lib instead of licp.lib).
Most of the code doesn't have exception handling. The code is written with that in mind.
int *p = new int[size];
if (p == NULL)
{
// handle this case...
// most probably return an error code
}
char *q = new char[size];
if (q == NULL)
{
delete[] p;
// handle this case...
// most probably return an error code
}
We also use the RAII technique. For instance, we have a object created on the stack that automatically waits on and releases a critical section.
We want to improve the stability of our SDK. We were thinking of adding exception handling but I'm not convinced that it is the right way to improve the stability. I have to admit that I don't have much experience with EH.
The code, in general, checks for divide by 0 or checks for NULL pointers before dereferencing it. But, it still happens that such a case will happen. Since divide by zero or dereferencing a NULL pointer don't throw an exception, I am wondering how much useful is it to go thru 100 000s of lines of code and add exception handling which will change the workflow and may cause memory leaks if not handled properly. I experimented with SEH but I don't think it makes sense to start using SEH and it is Microsoft specific, isn't it?.
In my mind, I think that if it would be more useful to review the existing code and simply check for possible crashes such as divide by zero that may have been missed.
Also, if I were to add exception-handling, how would I proceed? Modify all the modules at once or start from the bottom-up (meaning, if Module A calls Module B which calls Module C, I would modify C, then B then A since we release our software quite frequently and we would probably only have time to modify C before the next release).
Thank you!

I'd like to know the advantages and disadvantages of adding exception-handling to existing code.
You don't say what you mean precisely by "exception handling", so I'll start with something fundamental: standard C++ (you tagged the question as c++) requires you to write code that "handles exceptions", for all but trivial applications, otherwise your code is faulty. Various parts of the C++ standard library are permitted to throw exceptions, including the new that your sample code uses. Therefore your code is already likely to have the possibility that exceptions could be thrown within it, which it must "handle". What happens in that case? Basically, you must write "exception safe code".
It is an error for a program to leak resources in the face of exceptions. You use RAII so you should be OK.
It is an error for any object to enter an inconsistent state after an exception is throw. Ensuring that can be much more tricky.
You should first focus on making your code exception safe.

With Legacy code, you should introduce exception handling in a few places as schedule permits; either the least accessed areas of the code (to reduce the risk of errors to the rest of the code base) or to where they would produce the most benefit (citical error places).
I do not recommend stalling a legacy project just to add exception handling everywhere. The hardest part about legacy code is to modify it and keep it working. After all, its been tested and its behavior is well documented.

I agree with Raedwald that if you are using C++ without a very careful coding standard to avoid EH (ex: using nothrow new, avoiding standard containers, etc), which I'm assuming the legacy code did not, then the code is already broken and is likely to leak and do sporadic things already in the face of exceptions it can already encounter like bad_alloc or bad_cast if you rely on dynamic_cast.
That said, from a very pragmatic standpoint with a legacy codebase, chances are that the legacy code managed to get away with it. And after all, how many non-trivial applications can gracefully recover from bad_alloc exceptions without very explicit control over memory allocation? Not many, and it doesn't cause the entire world to come to a screeching halt.
So I actually don't recommend rewriting the legacy code to try to catch exceptions and use RAII everywhere. You might utilize RAII here and there in code you absolutely have to modify, but I'd try to look for reasons not to change it too much. Write tests for it and try to stabilize it and turn it into a black box; a library of functionality to be used, not maintained and changed while wading through endless LOC indefinitely.
Now the main reason I pitched in here and resurrected this old thread (apologies!) is because of this comment:
The code, in general, checks for divide by 0 or checks for NULL
pointers before dereferencing it. But, it still happens that such a
case will happen. Since divide by zero or dereferencing a NULL pointer
don't throw an exception [...]
In my strong opinion, you should not throw in response to things like null pointer access or divide by zero because those are programmer errors. Unless you're working in a mission-critical software where you want to gracefully recover even if the software is buggy in order to try to reduce the risk of costing lives or something like that, you don't want the application to gracefully recover in the event of programming mistakes. The reason you generally don't want to do that is because it has the downside of hiding bugs, making them silent, allowing users to ignore and work around them and maybe not even bother reporting them.
Instead for programmer mistakes you should generally favor assert which doesn't involve exceptions at all. If the assertion fails, the software in a debug build will come to a halt and typically display an error message telling you where the assertion failed down to the precise line of code. That is usually the quickest bet to detecting and fixing these programming mistakes when running a debugger in response to a bug report, so feel free to assert liberally.
Exceptions are most useful for external exceptional events outside of a programmer's control. An example would be reading a file that turns out to be corrupt. That's not within the programmer's control to handle so there it's appropriate to throw and recover. Another example is failing to connect to a server, a user jamming an abort button for an operation that is supposed to finish, etc. Those are exceptional external input events, not programmer mistakes.
The best way to recover from programmer mistakes like null pointer accesses and divide by zeros is to first detect them (assert is handy), write a test to reproduce it, fix it and get the test to pass, and call it a day, not throw exceptions and catch them while leaving those mistakes in there.

Related

If you're in the "we don't use exceptions" camp, then how do you use the standard library?

Note: I'm not playing the devil's advocate or anything like that here - I'm just genuinely curious since I'm not in this camp myself.
Most types in the standard library have either mutating functions that can throw exceptions (for instance if memory allocation fails) or non-mutating functions that can throw exceptions (for instance out of bounds indexed accessors). In addition to that, many free functions can throw exceptions (for instance operator new and dynamic_cast<T&>).
How do you practically deal with this in the context of "we don't use exceptions"?
Are you trying to never call a function that can throw? (I can't see how that'd scale, so I'm very interested to hear how you accomplish this if this is the case)
Are you ok with the standard library throwing and you treat "we don't use exceptions" as "we never throw exceptions from our code and we never catch exceptions from other's code"?
Are you disabling exception handling altogether via compiler switches? If so, how do the exception-throwing parts of the standard library work?
EDIT Your constructors, can they fail, or do you by convention use a 2-step construction with a dedicated init function that can return an error code upon failure (which the constructor can't), or do you do something else?
EDIT Minor clarification 1 week after the inception of the question... Much of the content in comments and questions below focus on the why aspects of exceptions vs "something else". My interest is not in that, but when you choose to do "something else", how do you deal with the standard library parts that do throw exceptions?
I will answer for myself and my corner of the world. I write c++14 (will be 17 once compilers have better support) latency critical financial apps that process gargantuan amounts of money and can't ever go down. The ruleset is:
no exceptions
no rtti
no runtime dispatch
(almost) no inheritance
Memory is pooled and pre-allocated, so there are no malloc calls after initialization. Data structures are either immortal or trivially copiable, so destructors are nearly absent (there are some exceptions, such as scope guards). Basically, we are doing C + type safety + templates + lambdas. Of course, exceptions are disabled via the compiler switch. As for the STL, the good parts of it (i.e.: algorithm, numeric, type_traits, iterator, atomic, ...) are all useable. The exception-throwing parts coincide with the runtime-memory-allocating parts and the semi-OO parts nicely so we get to get rid of all the cruft in one go: streams, containers except std::array, std::string.
Why do this?
Because like OO, exception offers illusory cleanliness by hiding or moving the problem elsewhere, and makes the rest of the program harder to diagnose. When you compile without "-fno-exceptions", all your clean and nicely behaved functions have to endure the suspicion of being failable. It is much easier to have extensive sanity checking around the perimeter of your codebase, than to make every operation failable.
Because exceptions are basically long range GOTOs that have an unspecified destination. You won't use longjmp(), but exceptions are arguably much worse.
Because error codes are superior. You can use [[nodiscard]] to force calling code to check.
Because exception hierarchies are unnecessary. Most of the time it makes little sense to distinguish what errored, and when it does, it's likely because different errors require different clean-up and it would have been much better to signal explicitly.
Because we have complex invariants to maintain. This means that there are code, however deep down in the bowels, that need to have transnational guarantees. There are two ways of doing this: either you make your imperative procedures as pure as possible (i.e.: make sure you never fail), or you have immutable data structures (i.e.: make failure recovery possible). If you have immutable data structures, then of course you can have exceptions, but you won't be using them because when you will be using sum types. Functional data structures are slow though, so the other alternative is to have pure functions and do it in an exception-free language such as C, no-except C++, or Rust. No matter how pretty D looks, as long as it isn't cleansed of GC and exceptions, it's an non-option.
Do you ever test your exceptions like you would an explicit code path? What about exceptions that "can never happen"? Of course you don't, and when you actually hit those exceptions you are screwed.
I have seen some "beautiful" exception-neutral code in C++. That is, it performs optimally with no edge cases regardless of whether the code it calls uses exceptions or not. They are really hard to write and I suspect, tricky to modify if you want to maintain all your exception guarantees. However, I have not seen any "beautiful" code that either throws or catches exceptions. All code that I have seen that interacts with exceptions directly have been universally ugly. The amount of effort that went into writing exception-neutral code completely dwarfs the amount of effort that was saved from the crappy code that either throws or catches exceptions. "Beautiful" is in quotes because it is not actual beauty: it is usually fossilized because editing it requires the extra burden of maintaining exception-neutrality. If you don't have unit tests that deliberately and comprehensively misuse exceptions to trigger those edge cases, even "beautiful" exception-neutral code decays into manure.
In our case, we disable the exceptions via the compiler (e.g -fno-exceptions for gcc).
In the case of gcc, they use a macro called _GLIBCXX_THROW_OR_ABORT which is defined as
#ifndef _GLIBCXX_THROW_OR_ABORT
# if __cpp_exceptions
# define _GLIBCXX_THROW_OR_ABORT(_EXC) (throw (_EXC))
# else
# define _GLIBCXX_THROW_OR_ABORT(_EXC) (__builtin_abort())
# endif
#endif
(you can find it in libstdc++-v3/include/bits/c++config on latest gcc versions).
Then you juste have to deal with the fact that exceptions thrown just abort. You can still catch the signal and print the stack (there is a good answer on SO that explains this), but you have better avoid this kind of things to happen (at least in releases).
If you want some example, instead of having something like
try {
Foo foo = mymap.at("foo");
// ...
} catch (std::exception& e) {}
you can do
auto it = mymap.find("foo");
if (it != mymap.end()) {
Foo foo = it->second;
// ...
}
I also want to point out, that when asking about not using exceptions, there's a more general question about standard library: Are you using standard library when you're in one of the "we don't use exceptions" camps?
Standard library is heavy. In some "we don't use exceptions" camps, like many GameDev companies for example, better suited alternatives for STL are used - mostly based on EASTL or TTL. These libraries don't use exceptions anyway and that's because eighth generation consoles didn't handle them too well (or even at all). For a cutting edge AAA production code, exceptions are too heavy anyway, so it's a win - win scenario in such cases.
In other words, for many programmers, turning exceptions off goes in pair with not using STL at all.
Note I use exceptions... but I have been forced not to.
Are you trying to never call a function that can throw? (I can't see how that'd scale, so I'm very interested to hear how you accomplish this if this is the case)
This would probably be infeasible, at least on a large scale. Many functions can land up throwing, avoid them entirely cripples your code base.
Are you ok with the standard library throwing and you treat "we don't use exceptions" as "we never throw exceptions from our code and we never catch exceptions from other's code"?
You pretty much have to be ok with that... If the library code is going to throw an exception and your code is not going to handle it, termination is the default behaviour.
Are you disabling exception handling altogether via compiler switches? If so, how does the exception-throwing parts of the standard library work?
This is possible (back in the day it was sometime popular for some project types); compilers do/may support this, but you will need to consult their documentation for what the result(s) would and could be (and what language features are supported under those conditions).
In general, when an exception would be thrown, the program would need to abort or otherwise exit. Some coding standards still require this, the JSF coding standard comes to mind (IIRC).
General strategy for those who "don't use exceptions"
Most functions have a set of preconditions that can be checked for before the call is made. Check for those. If they are not met, then don't make the call; fall back to whatever the error handling is in that code. For those functions that you can't check to ensure the preconditions are met... not much, the program will likely abort.
You could look to avoid libraries that throw exceptions - you asked this in the context of the standard library, so this doesn't quite fit the bill, but it remains an option.
Other possible strategies; I know this sounds trite, but pick a language that doesn't use them. C could do nicely...
...crux of my question (your interaction with the standard library, if any), I'm quite interested in hearing about your constructors. Can they fail, or do you by convention use a 2-step construction with a dedicated init function that can return an error code upon failure (which the constructor can't)? Or what's your strategy there?
If constructors are used, there are generally two approaches that are used to indicate the failure;
Set an internal error code or enum to indicate the failure and what the failure is. This can be interrogated after the object's construction and appropriate action taken.
Don't use a constructor (or at least only construct what cannot fail in the constructor - if anything) and then use an init() method of some sort to do (or complete) the construction. The member method can then return an error if there is some failure.
The use of the init() technique is generally favored as it can be chained and scales better than the internal "error" code.
Again, these are techniques that come from environments where exceptions do not exist (such as C). Using a language such as C++ without exceptions limits its usability and the usefulness of the breadth of the standard library.
Not trying to fully answer the questions you have asked, I will just give google as an example for code base which does not utilize exceptions as a mechanism to deal with errors.
In Google C++ code base, every functions which may fail return a status object which have methods like ok to specify the result of the callee.
They have configurated GCC to fail the compilation if the developer ignored the return status object.
Also, from the little open source code they provide (such as LevelDB library), it seems they are not using STL that much anyway, so exception handling become rare. as Titus Winters says in his lectures in CPPCon, they "Respect the standard, but don't idolize it".
I think this is an attitude question. You need to be in the camp of "I don't care if something fails".
This usually results in code, for which one needs a debugger (at the customer site) to find out, why suddenly something is not working anymore.
Also potentially people which are doing software "engineering" in this way, do not use very complex code. E.g. one would be unable to write code, which relies on the fact that it is only executed, if all n resources it relies on have been successfully allocated (while using RAII for these resources).
Thus: Such coding would result in either:
an unmanageable amount of code for error handling
an unmanageable amount of code to avoid executing code, which relies on successful allocation of some resources
no error handling and thus considerable higher amount of support and developer time
Note, that I'm talking about modern code, loading customer-provided dlls on demand and using child processes. There are many interfaces on which something can fail. I'm not talking about some replacement for grep/more/ls/find.

How should I handle exceptions in C++/Qt? [duplicate]

I was talking to a friend of mine that through my new code I didn't treat exceptions, just because I didn't know how to do it in C++. His answer surprised me: "why in the hell would you want to throw excetions?". I asked him why, but he didn't have a satisfying answer, so I googled it. One of the first pages I found was a blog entry, where the guy who posted wasn't totally against exceptions, but a religious war started in the replies: http://weblogs.asp.net/alex_papadimoulis/archive/2005/03/29/396141.aspx
Now I begin to wonder: is it that bad to throw an exception? For a student like I am, is it wrong to learn programming using exceptions as a normal thing? (When I throw exceptions, I catch them in another level of the code to treat them, most of the times). I have a code example, and I want to know what should I do:
int x;
cout << "Type an integer: ";
cin >> x;
Anything that is typed there that is not an integer will trigger an exception already, right? This exception should be treated there. But when I have a possible exception inside a class that is being used elsewhere in the program, should I make this method throw an exception so I can treat it wherever I call it or should I make it return a standard value when it has any problems?
The exception is always good, always bad, or something to be used in "exceptional" situations? Why?
The C++ iostreams classes do not, by default, use exception handling. Generally one should use exceptions for situations where an error can occur, but such errors are "unusual" and "infrequent" (such as a disk failing, the network being down, etc.). For error conditions that you do expect (such as the user providing invalid input), you should probably not use exception handling, unless the logic that needs to deal with this situation is far removed from the logic in which the situation is detected, in which case using an exception is the way to go. There is nothing wrong with using exceptions, and using exceptions where they are merited is definitely good... just avoid using them where if...else works just fine.
As to the why:
Exceptions often provide a simple, elegant way of handling unexpected errors, but:
Exception propagation, depending on the compiler and platform, may be slower than ordinary control flow, so if you can handle the situation locally, then that will be at least as fast... and you especially don't want to slow down the common, expected cases (such as invalid input). Also:
Exceptions require more type information to be present and also require code that is unrelated to throwing or catching exceptions to be "exception-safe" which is why some object to exceptions.
Question 1:
There is no reason not to use exceptions.
Whether to use exceptions or other techniques depends on the situation.
Exceptions are good to use when you can't fix the error locally.
(This should be an exceptional situation :-)
Error codes are good when you can fix the error locally.
Error codes are bad if you have a library that exposes an interface that returns an error code that needs to be manually checked. In the C world forgetting to check the error code was a significant source of problems.
Exceptions are good when you want to force the user of your interface to check for an error. If the user does not explicitly check and compensate; then the exception will propagate until either it is handled or the application exits.
Problems that come with exceptions:
If your code is a combination of C and C++. Functions with C ABI do not contain enough information for exceptions to propagate. Thus throwing an exception across a C function can (depending on the compiler and other factors) cause problems.
If you register a callback functions with a C library that uses C++ code. Then you must make sure that all exceptions are caught in the callback function and not allowed to propagate back to the C-library.
But this is true when combining any two languages. You can only use the most primitive features across language boundaries (and even that can take work if the languages do not align well). Therefore trying to use any advanced features is usually not supported.
Question 2:
C++ streams by default do not use exceptions.
This is because usually you want to handle the problem immediately.
In your example you use input as an example. In this situation you want to check the error and re-request the input.
int x;
cout << "Type an integer: ";
cin >> x;
while(!cin)
{
cin.clear();
std::cout << "Failed: What do you think an integer is? Try again: ";
cin >> x;
}
Note:
Personally I don't like the phrase 'Use exceptions in Exceptional circumstances". To me that is just to vague. vector::at() throws an exception. For me accessing off the end of an array is going to be exceptional (but for Joe student I doubt it will be exceptional (it will happen every second class as the lecturer throws a new curve ball at him/her)).
Thus I prefer the term "When the problem can not be fixed locally". A problem that can not be fixed locally is when something big has gone wrong (resource depletion (memory full throw bad_alloc()), coding error (access beyond array bounds (throw range_check()))) or any number of things that can not be fixed right there.
There is actually a legitimate reason behind why you shouldn't use exceptions.
The problem is when you throw exception across boundaries (e.g. from one DLL and try...catch it in another DLL) sometimes things can go very wrong. I got a slap on the wrist too when I used it in one of my projects.
Just google it you'll find all sorts of post on this topic, at least it was a problem few years ago when I was still a fulltime C++ developer :)
I tend to follow this convention for internal parts of my applications code:
Do not throw exceptions of your own.
Catch any exception that could be expected from your calls to other code inmediately. Treat it accordingly, for example returning an error code, or "false" with the meaning of no success.
However when designing components, I do use component-scope exceptions, like for example, if connecting to a required database (one which is set up by the installer) fails. Or when you try to call any method violating its preconditions. In general, preconditions are expressed with assertions; however, in the public layer of your component, they should be checked and an exception thrown if they are violated, otherwise the caller has a hard job finding what they are doing wrong. (An alternative is of course to use a debug version, in which failed assertions will scream at you; but this is not always practical - distributing two binaries, keeping them up to date, etc.)
In my opinion, the only general rule is to be consistent and write correct code - choose some way to handle the erroneous/exceptional situations, and follow it consistently.
I think exception handling/throwing can be boiled down to the following:
Use RAII (or using in C#, or with in Python) so your code is exception safe.
Catch exceptions if there's a chance to recover from the error, else let them bubble up.
Throw exception only if you have something useful to add.
Consider a hypothetical example where you're using a serial port communication library to communicate with an external sensor of sorts. Furthermore:
The serial port communication library reports errors by throwing exceptions.
The sensor itself can communicate certain error messages through status codes in cases when it's no longer able to acquire data, when it's functioning outside its max/min operating conditions, etc.
You're using RAII (Resource Acquisition Is Initialization), so if the serial port library throws an exception you wouldn't have to worry about releasing any acquired resources.
If the serial port library thrown an exception, you can:
Catch the exception and try to recover from it somehow, e.g. by reinitializing the library.
Catch the exception, wrap it in your own, and then throw the new exception up the call stack.
Option #1 is unlikely in most cases. And option #2 would probably not add any valuable information to what's already in the original exception.
So usually it's best to allow original exception to bubble up (this is again assuming the RAII is in place and no clean up is needed).
On the other hand, if the sensor itself reports an error code, then it makes a lot of sense to throw your own exception.
This one is also a very interesting and controversial reading on the argument:
http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx
Throw an exception if, and only if, the alternative is failure to meet a post condition or to maintain an invariant.
That advice replaces an unclear subjective decision (is it a good idea) with a technical, precise question based on design decisions (invariant and post conditions) you should already have made.
If you just blindly go and say I won't use exceptions it means you're not going to use most of the STL. That means you need to write your own classes for strings/vector etc etc ...
Plus exceptions are a much cleaner way of doing error handling (IMHO) and if you already do RAII then adding exceptions is not much harder.
Read everything in Section 14 upto section 14.2 of Bjarne Stroustrup: "C++ programming Language Third Edition"
It is the most convincing answer I have come across.

Better language feature than exception handling in C++? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
(not sure if it's only a C++ thing)
Exception handling is hard to learn in C++ and is certainly not a perfect solution but in most cases (other than some specific embedded software contexts) it's certainly the better solution we currently have for exception handling.
What about the future?
Are there other known ways to handle errors that are not implemented in most languages, or are only academical research?
Put another way: are there (suposedly) known better (unperfect is ok) ways to handle errors in programming languages?
Well, there's always been return codes, errno and the like. The general problem is that these can be ignored or forgotten about by programmers who are unaware that a particular call can fail. Exceptions are frequently ignored or missed by programmers too. The difference is that if you don't catch an exception the program dies. If you don't check a return code, the program continues on operating on invalid data. Java tried to force programmers to catch all of their exceptions by creating checked exceptions, which cause a compilation error if you don't specify exactly when they can be propagated and catch them eventually. This turned out to be insanely annoying, so programmers catch the exceptions with catch(...){/* do nothing*/} (in C++ parlence) as close to their source as possible, and the result is no better than ignoring a return code.
Besides these two error techniques, some of the functional languages support the use of various monadic return types which can encapsulate both errors and return values (e.g. Scala's Either type, Option type, or a monad that lets you return an approximate answer along with failure log). The advantage to these is that the only way to work with the successful return value is to execute code inside the monad, and the monad ensures that the code isn't run if there was a failure. (It's rather complicated to explain for someone who isn't a Haskell or Scala programmer.) I haven't worked with this model so much, but I expect it would be as annoying to some people as checked exceptions are.
Basically, IMO, error checking is a matter of attitude. You have three options:
Realize you have to deal with it, accept that fact cheerfully, and take the effort to write correct error handling code. (Any of them)
Use language features that force you to deal with it, and get annoyed because you don't want to deal with it, particularly when you're sure the error will never happen. (Checked Exceptions, Monads)
Use langauge features that allow you to ignore it easily, and write unsafe code because you ignored it. (Unchecked Exceptions, Return Codes)
Get the worst of both options 2 and 3 by using language features that force you to deal with it, but deali with every error in a way that explicitly ignores it. (Checked Exceptions, Monads)
Obviously, you should try to be a #1 type programmer.
Assuming you want your code to do different things according to whether an error occurs or not, you have basically three options:
1) Make this explicit everywhere in the code (C-style error return value checking). The main perceived disadvantage is that it's verbose.
2) Use non-local control flow to separate error-handling code from the "usual path" (exceptions). The main perceived disadvantage is keeping track of all the places your code can go next, especially if documented interfaces don't always list them all. Java's experiment with checked exceptions to "deal with" the latter issue weren't entirely successful either.
3) Sit on errors until "later" (IEEE-style sticky error bits and quiet NaNs, C++ error flags on streams), and check them only when convenient for the caller. The main perceived disadvantage is that setting and clearing errors requires careful use by everyone, and also that information available at the site of the error may be lost by the time it's handled.
Take your pick. (1) looks bloated and complex, and newbies mess it up by not checking for errors properly, but each line of code is easy to reason about. (2) looks small and simple, but each line of code might cause a jump to who-knows-where, so newbies mess it up by not implementing exception guarantees properly, and everyone sometimes catches exceptions in the wrong places or not at all. (3) is great when designed well, but you never know which of several possibilities each line of code is actually doing, so in a UB-rich environment like C++ that's easy to mess up too.
I think the underlying problem is basically hard: handling errors explicitly increases the branches in your code. Handling errors quietly increases the amount of state that you need to reason about, in a particular bit of code.
Exceptions also have the "is it truly exceptional?" problem. You could prevent exceptions from causing confusing control flow, by throwing them only in cases that your entire program can't recover from. But then you can't use them for errors which are recoverable from the POV of your program but not from the POV of the subsystem, so for those cases you fall back to the disadvantages of either (1) or (3).
I can't say that it is better than exceptions, but one alternative is the way that Erlang developers implement fault tolerance, known as "Let it fail". To summarize: each task gets spawned off as a separate "process" (Erlang's term for what most people call "threads"). If a process encounters an error, it just dies and a notification is back to the controlling process, which can either ignore it or take some sort of corrective action.
This supposedly leads to less complex and more robust code, as the entire program won't crash or exit due to lack of error handling. (Note that this robustness relies on some other features of the Erlang language and run-time environment.)
Joe Armstrong's thesis, which includes a section on how he envisions fault-tolerant Erlang systems, is available for download: http://www.erlang.org/download/armstrong_thesis_2003.pdf
Common Lisp's condition system is regarded as being a powerful superset beyond what exceptions let you do.
The fundamental problem with exception handling in systems I've seen is that if routine X calls routine Y, which calls routine Z, which throws an exception, there's no clean way for Y to let its caller distinguish among a number of situations:
The call failed for some reason that Y doesn't know about, but X might; from Y's perspective, if X knows why Z failed, X should expect to recover.
The call failed for some reason that Y doesn't know about, but its failure caused Y to leave some data structures in an invalid state.
The call failed for some reason that Y does know about; from its perspective, if the caller can handle the fact that the call won't return the expected result, X should recover.
The call failed because the CPU is catching fire.
This difficulty stems, I think, from the fact that exception types are centered around the question of what went wrong--a question which in many cases is largely orthogonal to the question of what to do about it. What I would like to see would be for exceptions to include a virtual "isSatisfied" method, and an effort to swallow an exception whose isSatisfied method returns false to throw a wrapped exception whose isSatisfied method would chain the nested one. Some types of exceptions like trying to add a duplicate key to a non-corrupted dictionary would provide a parameterless AcknowledgeException() method to set isSatisfied. Other exceptions implying data corruption or other problems would require the that either an AcknowledgeCoruption() method be passed the corrupted data structure, or that the corrupt data structure be destroyed. Once a corrupt data structure is destroyed in the process of stack unwinding, the universe would be happy again.
I'm not sure what the best architecture would be, but providing a means by which exceptions can communicate the extent to which the system state is corrupt or intact would go a long way toward alleviating the problems with existing architectures.

To throw or not to throw exceptions?

I was talking to a friend of mine that through my new code I didn't treat exceptions, just because I didn't know how to do it in C++. His answer surprised me: "why in the hell would you want to throw excetions?". I asked him why, but he didn't have a satisfying answer, so I googled it. One of the first pages I found was a blog entry, where the guy who posted wasn't totally against exceptions, but a religious war started in the replies: http://weblogs.asp.net/alex_papadimoulis/archive/2005/03/29/396141.aspx
Now I begin to wonder: is it that bad to throw an exception? For a student like I am, is it wrong to learn programming using exceptions as a normal thing? (When I throw exceptions, I catch them in another level of the code to treat them, most of the times). I have a code example, and I want to know what should I do:
int x;
cout << "Type an integer: ";
cin >> x;
Anything that is typed there that is not an integer will trigger an exception already, right? This exception should be treated there. But when I have a possible exception inside a class that is being used elsewhere in the program, should I make this method throw an exception so I can treat it wherever I call it or should I make it return a standard value when it has any problems?
The exception is always good, always bad, or something to be used in "exceptional" situations? Why?
The C++ iostreams classes do not, by default, use exception handling. Generally one should use exceptions for situations where an error can occur, but such errors are "unusual" and "infrequent" (such as a disk failing, the network being down, etc.). For error conditions that you do expect (such as the user providing invalid input), you should probably not use exception handling, unless the logic that needs to deal with this situation is far removed from the logic in which the situation is detected, in which case using an exception is the way to go. There is nothing wrong with using exceptions, and using exceptions where they are merited is definitely good... just avoid using them where if...else works just fine.
As to the why:
Exceptions often provide a simple, elegant way of handling unexpected errors, but:
Exception propagation, depending on the compiler and platform, may be slower than ordinary control flow, so if you can handle the situation locally, then that will be at least as fast... and you especially don't want to slow down the common, expected cases (such as invalid input). Also:
Exceptions require more type information to be present and also require code that is unrelated to throwing or catching exceptions to be "exception-safe" which is why some object to exceptions.
Question 1:
There is no reason not to use exceptions.
Whether to use exceptions or other techniques depends on the situation.
Exceptions are good to use when you can't fix the error locally.
(This should be an exceptional situation :-)
Error codes are good when you can fix the error locally.
Error codes are bad if you have a library that exposes an interface that returns an error code that needs to be manually checked. In the C world forgetting to check the error code was a significant source of problems.
Exceptions are good when you want to force the user of your interface to check for an error. If the user does not explicitly check and compensate; then the exception will propagate until either it is handled or the application exits.
Problems that come with exceptions:
If your code is a combination of C and C++. Functions with C ABI do not contain enough information for exceptions to propagate. Thus throwing an exception across a C function can (depending on the compiler and other factors) cause problems.
If you register a callback functions with a C library that uses C++ code. Then you must make sure that all exceptions are caught in the callback function and not allowed to propagate back to the C-library.
But this is true when combining any two languages. You can only use the most primitive features across language boundaries (and even that can take work if the languages do not align well). Therefore trying to use any advanced features is usually not supported.
Question 2:
C++ streams by default do not use exceptions.
This is because usually you want to handle the problem immediately.
In your example you use input as an example. In this situation you want to check the error and re-request the input.
int x;
cout << "Type an integer: ";
cin >> x;
while(!cin)
{
cin.clear();
std::cout << "Failed: What do you think an integer is? Try again: ";
cin >> x;
}
Note:
Personally I don't like the phrase 'Use exceptions in Exceptional circumstances". To me that is just to vague. vector::at() throws an exception. For me accessing off the end of an array is going to be exceptional (but for Joe student I doubt it will be exceptional (it will happen every second class as the lecturer throws a new curve ball at him/her)).
Thus I prefer the term "When the problem can not be fixed locally". A problem that can not be fixed locally is when something big has gone wrong (resource depletion (memory full throw bad_alloc()), coding error (access beyond array bounds (throw range_check()))) or any number of things that can not be fixed right there.
There is actually a legitimate reason behind why you shouldn't use exceptions.
The problem is when you throw exception across boundaries (e.g. from one DLL and try...catch it in another DLL) sometimes things can go very wrong. I got a slap on the wrist too when I used it in one of my projects.
Just google it you'll find all sorts of post on this topic, at least it was a problem few years ago when I was still a fulltime C++ developer :)
I tend to follow this convention for internal parts of my applications code:
Do not throw exceptions of your own.
Catch any exception that could be expected from your calls to other code inmediately. Treat it accordingly, for example returning an error code, or "false" with the meaning of no success.
However when designing components, I do use component-scope exceptions, like for example, if connecting to a required database (one which is set up by the installer) fails. Or when you try to call any method violating its preconditions. In general, preconditions are expressed with assertions; however, in the public layer of your component, they should be checked and an exception thrown if they are violated, otherwise the caller has a hard job finding what they are doing wrong. (An alternative is of course to use a debug version, in which failed assertions will scream at you; but this is not always practical - distributing two binaries, keeping them up to date, etc.)
In my opinion, the only general rule is to be consistent and write correct code - choose some way to handle the erroneous/exceptional situations, and follow it consistently.
I think exception handling/throwing can be boiled down to the following:
Use RAII (or using in C#, or with in Python) so your code is exception safe.
Catch exceptions if there's a chance to recover from the error, else let them bubble up.
Throw exception only if you have something useful to add.
Consider a hypothetical example where you're using a serial port communication library to communicate with an external sensor of sorts. Furthermore:
The serial port communication library reports errors by throwing exceptions.
The sensor itself can communicate certain error messages through status codes in cases when it's no longer able to acquire data, when it's functioning outside its max/min operating conditions, etc.
You're using RAII (Resource Acquisition Is Initialization), so if the serial port library throws an exception you wouldn't have to worry about releasing any acquired resources.
If the serial port library thrown an exception, you can:
Catch the exception and try to recover from it somehow, e.g. by reinitializing the library.
Catch the exception, wrap it in your own, and then throw the new exception up the call stack.
Option #1 is unlikely in most cases. And option #2 would probably not add any valuable information to what's already in the original exception.
So usually it's best to allow original exception to bubble up (this is again assuming the RAII is in place and no clean up is needed).
On the other hand, if the sensor itself reports an error code, then it makes a lot of sense to throw your own exception.
This one is also a very interesting and controversial reading on the argument:
http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx
Throw an exception if, and only if, the alternative is failure to meet a post condition or to maintain an invariant.
That advice replaces an unclear subjective decision (is it a good idea) with a technical, precise question based on design decisions (invariant and post conditions) you should already have made.
If you just blindly go and say I won't use exceptions it means you're not going to use most of the STL. That means you need to write your own classes for strings/vector etc etc ...
Plus exceptions are a much cleaner way of doing error handling (IMHO) and if you already do RAII then adding exceptions is not much harder.
Read everything in Section 14 upto section 14.2 of Bjarne Stroustrup: "C++ programming Language Third Edition"
It is the most convincing answer I have come across.

C++ - Arguments for Exceptions over Return Codes

I'm having a discussion about which way to go in a new C++ project. I favor exceptions over return codes (for exceptional cases only) for the following reasons -
Constructors can't give a return code
Decouples the failure path (which should be very rare) from the logical code which is cleaner
Faster in the non-exceptional case (no checking if/else hundreds of thousands of times)
If someone screws up the return code settings (forgets to return FAIL) it can take a very long time to track down.
Better information from the message contained in the error. (It was pointed out to me that a return enum could do the same for error codes)
From Jared Par Impossible to ignore without code to specifically designed to handle it
These are the points I've come up with from thinking about it and from google searches. I must admit to being predisposed to exceptions having worked in C# for the past couple of years. Please post further reasons for using exceptions over return codes. For those who prefer return codes, I would also be willing to listen to your reasoning. Thanks
I think this article sums it up.
Arguments for Using Exceptions
Exceptions separate error-handling code from the normal program flow and thus make the code more readable, robust and extensible.
Throwing an exception is the only clean way to report an error from a constructor.
Exceptions are hard to ignore, unlike error codes.
Exceptions are easily propagated from deeply nested functions.
Exceptions can be, and often are, user defined types that carry much more information than an error code.
Exception objects are matched to the handlers by using the type system.
Arguments against Using Exceptions
Exceptions break code structure by creating multiple invisible exit points that make code hard to read and inspect.
Exceptions easily lead to resource leaks, especially in a language that has no built-in garbage collector and finally blocks.
Learning to write exception safe code is hard.
Exceptions are expensive and break the promise to pay only for what we use.
Exceptions are hard to introduce to legacy code.
Exceptions are easily abused for performing tasks that belong to normal program flow.
The best case I've heard for preferring return codes over exceptions is simply this:
Writing exception-safe code is hard [in C++].
With a great deal of recent experience in C# myself, I can empathize with your desire to use exceptions, but unfortunately C++ isn't C#, and a lot of things that we can get away with in C# can be ultimately deadly in C++.
A good summation of the case for and against can be found in Google's style guidelines. In short:
Pros:
Exceptions allow higher levels of an application to decide how to
handle "can't happen" failures in
deeply nested functions, without the
obscuring and error-prone bookkeeping
of error codes.
Exceptions are used by most other modern languages. Using them in
C++ would make it more consistent with
Python, Java, and the C++ that others
are familiar with.
Some third-party C++ libraries use exceptions, and turning them off
internally makes it harder to
integrate with those libraries.
Exceptions are the only way for a constructor to fail. We can simulate
this with a factory function or an
Init() method, but these require heap
allocation or a new "invalid" state,
respectively.
Exceptions are really handy in testing frameworks.
Cons:
When you add a throw statement to an existing function, you must
examine all of its transitive callers.
Either they must make at least the
basic exception safety guarantee, or
they must never catch the exception
and be happy with the program
terminating as a result. For instance,
if f() calls g() calls h(), and h
throws an exception that f catches, g
has to be careful or it may not clean
up properly.
More generally, exceptions make the control flow of programs difficult
to evaluate by looking at code:
functions may return in places you
don't expect. This results
maintainability and debugging
difficulties. You can minimize this
cost via some rules on how and where
exceptions can be used, but at the
cost of more that a developer needs to
know and understand.
Exception safety requires both RAII and different coding practices.
Lots of supporting machinery is needed
to make writing correct exception-safe
code easy. Further, to avoid requiring
readers to understand the entire call
graph, exception-safe code must
isolate logic that writes to
persistent state into a "commit"
phase. This will have both benefits
and costs (perhaps where you're forced
to obfuscate code to isolate the
commit). Allowing exceptions would
force us to always pay those costs
even when they're not worth it.
Turning on exceptions adds data to each binary produced, increasing
compile time (probably slightly) and
possibly increasing address space
pressure.
The availability of exceptions may encourage developers to throw them
when they are not appropriate or
recover from them when it's not safe
to do so. For example, invalid user
input should not cause exceptions to
be thrown. We would need to make the
style guide even longer to document
these restrictions!
I suggest reading through and understanding the pros and cons, then making a decision for your own project based on these. You don't have the same software that google has, so what makes sense for them may not make sense for you (which is why I omitted their conclusion).
IMHO, the #1 reason to prefer exceptions over return codes is you can't silently ignore an exception. Doing so requires at least a minimum amount of extra code.
Use exceptions for exceptional error conditions. You have some good arguments for, and I'd like to attack some arguments against.
First, the standard C++ library uses exceptions itself, all over the place. You can't use container classes or iostreams without having them present. Since a lot of the useful features are going to use them, trying to get along without them is going to present a lot of problems.
Second, it isn't hard to write exception-safe code once you've learned how to do it. It requires consistent RAII, but that's how you should write anyway. You should adopt a construct-commit approach, but that is frequently an advantage, and avoids some subtle bugs. (For example, the self-assignment problem disappears entirely with a copy-swap approach.) In my experience, exception-safe code looks better in general. It is something C++ programmers have to learn, but there's lots of things C++ programmers have to learn, and this isn't that much more.
Third, provided you limit exceptions to exceptional cases, there should be minimal effects on performance. And, as Pavel Minaev has pointed out, if you have to pass error codes back with results, there's the possibility of effects on performance, since C++ isn't set up for easy returns of multiple values.
Fourth, it is indeed difficult to make older code exception-safe. However, this is a new project.
So, I see no good reasons not to throw exceptions in exceptional circumstances, and plenty of reasons to do so.
As a general rule. when recovery is possible and expected then use return codes.
When recovery is not possible or not desired then use exceptions.
Error handling is difficult, writing clean code with and without exceptions is - difficult.
As this is a new project, you don't have to worry about making old code exception safe, however you do have to worry about writing clean clear code.
Do so by using exceptions where appropriate.
Faster in the non-exceptional case (no checking if/else hundreds of thousands of times)
In the non-exceptional case, it's a single comparison to determine that E_SUCCESS was returned.
If someone screws up the return code settings (forgets to return FAIL) it can take a very long time to track down.
If someone fails to check the exceptions, it can be difficult to notice until you actually get an exception thrown there. If you're dealing with error codes, you know just by looking at it whether they're checking for them or not.
Use what makes sense. I think both have a place. There are situations where error codes are nearly impossible to use (returning failure from a constructor, for example)
Other times, error codes are just more convenient. They're easier to deal with in cases where you expect them to happen. Exceptions are for exceptional errors - the ones that aren't supposed to happen, but might do so once in a blue moon. Error codes are a lot more convenient for errors that are expected to happen regularly, and can be handled locally. Exceptions are most useful in cases where the error must be handled further up the call stack.
Also, exceptions aren't necessarily faster in the non-exceptional case. Often, they require extra exception handling code in function prolog and epilogs which has to be executed every time the function is called, whether or not it throws an exception.
Since many others have already provided the technical reasons for using exceptions over error codes, I will give a practical one.
I work on a complex system which uses return codes instead of exceptions. Now, this is very well designed code, but I would bet that, on average, about 70% of the code in every function is error handling code. A typically function looks something like this:
long Foo( )
{
long retCode = MoveStage( );
if ( retCode != RetCode_OK )
{
logger->LogError( __LINE__, __FILE__, "some message" );
return( retCode );
}
int someConfigVar = 0;
long retCode = GetConfigVar( "SomeVarName", someConfigVar );
if ( retCode != RetCode_OK )
{
logger->LogError( __LINE__, __FILE__, "some message" );
return( retCode );
}
long retCode = DoSomething( );
if ( retCode != RetCode_OK )
{
logger->LogError( __LINE__, __FILE__, "some message" );
return( retCode );
}
// and on and on and on...
}
The code is full of this and is hard to follow. On top of that, in many places the return code is ignored completely because we know that the call will not fail. Every function returns a ret code, so what you would normally return as the output of the function has to be returned as an out parameter. Also, all of these functions just return the retCode on error, so we just bubble that damn retCode to the top if something bad happens. You cannot centralize your error handling strategy this way, it becomes a messy headache.
It is very hard to write exception safe code. A completely contrived example is :-
void Class::Method()
{
i++;
SomeCallThatMightThrow();
j++;
}
Replace i++ and j++ with any two variables, resources, states that must remain synchronous. Garbage collection saved us from having to remember to pair our new's and deletes. Ironically, old fashioned explicit return code testing saves us from having to carefully analyse every function that might throw exceptions to check that they havn't screwed with the post-conditions.
One of the things I like about C++ is that it's very easy to think how the higher-level features might be implemented in terms of C features (which are easy to understand in terms of assembly). Exceptions for C++ break this mold. To get this level of understanding I have to do a lot. Just read this and you'll spend a lot of time scratching your head before you understand it.
Furthermore, exceptions require you to have good discipline making your code exception safe, and resource leak free. This means using RAII for anything that holds a resource ..
Additionally, exceptions have been shown when I have measured them to be a many, many orders of magnitude slower compared to a simple return code.
Well then they say you should only throw in exceptional circumstances, but how do you communicate the non-exceptional, expected, often-occuring errors. Well return codes of course! :)
I don't see how the benefits are worth it.
Constructors can't give a return code
(except if you are possibly throwing exceptions in a constructor you are in for a world of hurt)
Decouples the failure path (which should be very rare) from the logical code which is cleaner
(Opens up a much wider failure path. C++ exceptions are not like C# at all. I love C# exceptions. C++ exceptions are worse than useless. Partly due to implementation, partly due to what c++ is and isn't)
Faster in the non-exceptional case (no checking if/else hundreds of thousands of times)
(Not really. You have to check the same number of errors no matter what, you just don't see where they get checked. Also, there are errors that matter and ones that don't or at least matter to your code, so you don't have to check every single thing (do you check to see if new threw an error?))
If someone screws up the return code settings (forgets to return FAIL) it can take a very long time to track down.
(I'll take a million such errors over any one of the common errors that come about with C++ exceptions)
Better information from the message contained in the error. (It was pointed out to me that a return enum could do the same for error codes)
(Well, how do you implement your error handling? That's up to you, isn't it? You can have exceptions that give no useful information or error codes that log out extemsive data on failure. In C++ they seem to never give useful info in the cases you really want them to)
From Jared Par Impossible to ignore without code to specifically designed to handle it
(Sure, but this code is usually useless code. It's like passing a law saying everyone has to have bug free programs. The people who don't don't obey such laws anyway and for the people who do they already handle errors where they should anyway)
As for reasons against:
Wanting your program to actually work at least some of the time.
performance.
Ideology. If it's an error we are not supposed to 'recover' from it. We either die with an error message, log and continue, or completely ignore it. If we could fix it it wouldn't be an error, but a feature...and if you use code like that intentionally no debugging tools in the world are going to save you.
Mostly one.