I am just learning how to handle errors in my C++ code. I wrote this example that looks for a text file called some file, and if its not found will throw an exception.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int array[90];
try
{
ifstream file;
file.open("somefile.txt");
if(!file.good())
throw 56;
}
catch(int e)
{
cout<<"Error number "<<e<<endl;
}
return 0;
}
Now I have two questions. First I would like to know if I am using Exceptions correctly. Second, (assuming the first is true) what is the benefit to using them vs an If else statement?
"Correctly" is a value judgment, but (unlike other classes) there's a major benefit from exceptions classes being a monolithic hierarchy, so I'd generally advise throwing something derived from std::exception, not simply an int.
Second, it's open to question whether an incorrect file name is sufficiently unexpected to qualify as a good reason to throw an exception at all.
As to benefits vs. an if/else statement: there are a couple. First, exceptions let you segregate the code that deals with errors, so the main idea and readability of the code don't get lost in a maze of error handling. Second, when you have several layers of code between throwing and catching the exception, the code that throws the exception may not know how it should really be handled. Your code, for example, uses std::cout to report the problem -- but most such code would report errors on std::cerr instead. You can change from one to the other without any change to the code that tried to open the file (which might be deep in a library, and have no clue of which should be used for this application -- and might be used in an application where both are wrong, and MessageBox was preferred).
First I would like to know if I am using Exceptions correctly.
Yes, though generally you want your exceptions to derive from std::exception.
Second, (assuming the first is true) what is the benefit to using them vs an If else statement?
For the given example, nothing. The benefit of exceptions comes when you have
many deep nested functions, like this.
#include <stdexcept>
#include <iostream>
#include <string>
void anErrorFunc(const std::string& x)
{
ifstream file;
file.open(x);
if (!file)
throw std::runtime_error("Could not open file");
}
void someOtherFunction(const std::string& y)
{
//Do stuff
anErrorFunc(y);
//Do other stuff
}
int main()
{
try {
someOtherFunction("somefile.txt");
} catch (std::exception &ex) {
std::cout << "Ouch! That hurts, because: "
<< ex.what() << "!\n";
}
}
Note that the exception will be caught in main(), and someOtherFunction
does not have to worry about dealing with passing through failure return codes.
Well, you are using exception correctly in that there is nothing wrong with your code. That said, typically we do not throw primitive types around (even though you can). It is generally a better idea to throw an object that derives from std::exception, and even better to throw an std::exception that is also a boost::exception.
When things are very simple and the handling code and the throwing code are in the same function, then there really is no reason to use exceptions instead of if statements (and, indeed, it would be faster and more efficient to use if...else in that particular case). However, in most situations, the point where the error is discovered and you need to report it is far removed from the logic where the error is to be handled. In many cases the error-recovery logic is specific to the application in question and the logic where the error is discovered cannot make a sensible choice about how to recover from the error, hence the need to throw.
Another benefit of exception handling is that the type of the exception can be used to convey the type of error that occurred. Usually the types in exception hierarchies are much more meaningful than those error codes that end up being used in C code. Also, you cannot ignore an exception as easily as you can ignore an error code; while you can ignore an exception, it will cause the program to die a horrible death. By contrast, if a C function returns an error status code, and you ignore it, it's possible to continue executing and get silently wrong results... in that sense, the use of exceptions is much safer than using error codes.
You may also be interested in reading about exceptions and error handling from the C++ FAQ Lite.
You are not using exceptions correctly. Your code has a much simpler equivalent, without exceptions, which provides the same behaviour.
Exceptions are for when you can't test the results of a function call with other methods. In this case you can, so you shouldn't use exceptions.
As a corollary, you shouldn't throw and catch the exception in the same function body - just do whatever you want to do instead of throwing it.
Syntactically speaking, your code is correct. Idiomatically speaking, maybe not so much -- or at least this depends on the context. When a file can't open then we might do our handling right there inside that if( !file.good() ) if it's perfectly common and possible to happen. For example, if the user asks to open a file in a text editor then it's perfectly plausible and common that the file doesn't exist. On the other hand, if the editor can't find the spelling corpus file then that means something is (arguably) terribly wrong. The program wasn't probably installed, or the user messed around with that file -- anything is possible.
In C++ we use exceptions for exceptional cases. That is, cases that are really not meant to happen and that we don't "accept" to happen. This is as opposed to a user file not opening, or an invalid user input, or no internet connection: these are all examples of perfectly valid things happening, common situations, things we expect to happen sooner or later in a program's run. They aren't exceptional.
Now, what are the benefits of using exceptions compared to conditionals? Allow me to extend this question to any other jump (goto) mechanism: returns as well as conditionals. Exceptions are more expressive if that's what you want to say: if you are dealing with an exceptional case then use exceptions. Exceptions also get more done than plain conditionals, in an analogous way to that of virtual functions getting more done than conditionals. The right code-block will be executed depending on the exception, but also the right scope will handle the exception depending on the handlers.
There are other advantages to exceptions compared with conditionals: exceptions separate error-handling from other code. They allow associating arbitrary data and actions with an error state. They allow communicating success states (via a return) as well as error state (via a throw). And the list goes on...
Technically speaking and at the lowest level exceptions are a sophisticated jump mechanism. Back in the butterfly-days people invented the if conditional as a somewhat-sophisticated goto in order to enhance expressiveness (because a goto can be used for anything really) and to reduce programmer errors. The looping constructs such as the C for loop are also in essence a sophisticated jump with sparkles and rainbow colours, again for reducing errors and enhancing expressiveness. C++ introduced its new casting operators for the same reasons.
So there: exceptions aren't magic, just something somewhat new in the scene compared to conditionals and loops. Don't use them when you don't mean to, just like you don't use a loop when you really mean to use a conditional.
Syntactically what you're doing is right. Style-wise, as others have noted, you should be throwing something descended from std::exception.
As to part two of your question, I'd like to go into more detail on that.
The whole point of exceptions is to separate policy from implementation. As Billy ONeal said, you get no benefit at all from using exceptions within the same function that an if statement wouldn't make better. You need to be deeply nested in function calls for it to make sense.
In most code, your high level code has enough information and context to know what to do about errors, but no mechanism to detect them. Your low level code can detect the errors but has none of the information needed to deal with them.
The traditional means of coping with this -- returning error codes -- has a few problems:
It clutters up the code with error handling code to the point that the actual logic is obfuscated.
It relies on programmers not being lazy and checking EVERY error code return, an often foolhardy assumption. (C programmers, be honest here: when was the last time you checked the return value of printf?)
It adds the overhead of error checking and handling to EVERY function call whether there's an error or not.
Exceptions solve these issues (with varying degrees of success).
Exceptions solve #1 by only having exception-related code at the point of detection and at the point of handling. Intervening functions don't get cluttered with handling for obscure errors that they themselves have no interest in nor capability of dealing with.
They solve #2 by forcing handling. You can't ignore an exception. You have to take action on them. (Lazy programmers can still catch all exceptions and then ignore them, but here their crippling inability to program is now highlighted for all to see.)
They solve #3 (when not naively implemented) by having near-zero costs when not used, albeit often at a very, very high cost when actually used.
This is not to say that exceptions are the end-all/be-all of error handling. The disadvantages:
Exceptions are usually very costly when used. They have to be eschewed, despite their advantages, if performance is paramount.
Exceptions lead to very opaque code at times. They are non-local transfers of control -- effectively slightly safer versions of goto statements, but across functions. An exception can transfer control from hundreds of layers deep in your code in source files not even slightly related to the ones you're working on (and, in fact, quite possibly not even accessible to you). This kind of "spooky action at a distance" can make code very difficult to figure out.
"Checked exceptions" can actually be worse for noise generation than the old-style if handling. They tend to be more verbose, you see, than if or switch statements and the fact that you must handle checked exceptions for the code to even compile makes them a liability to many situations.
Because of their often high cost of use, carelessly using them for all error handling can make your code slow and bloated.
Related
Exceptions vs assert has been asked here before: Design by contract using assertions or exceptions?, Assertion VS Runtime exception, C++ error-codes vs ASSERTS vs Exceptions choices choices :(, Design by contract using assertions or exceptions?, etc. (*) There are also books, like Herb Sutter's Coding Standards that talk about this. The general consensus seems to be this:
Use assertions for internal errors, in the sense that the user of the module and the developer are one and the same person/team. Use exceptions for everything else. (**)
This rule makes a lot of sense to me, except for one thing. I am a scientist, using C++ for scientific simulations. In my particular context, this means that I am the sole user of most of my code. If I apply this rule, it means I never have to use exceptions? I guess not, for example, there are still I/O errors, or memory allocation issues, where exceptions are still necessary. But apart from those interactions of my program with the "outside world", are there other scenarios where I should be using exceptions?
In my experience, many good programming practices have been very useful to me, in spite of those practices being designed mostly for large complex systems or for large teams, while my programs are mostly small scientific simulations which are written mostly by me alone. Hence this question. What good practices of exception use apply in my context? Or should I use only asserts (and exceptions for I/O, memory allocation, and other interactions with the "outside world")?
(*) I hope that after reading the complete question, you agree that this is not a duplicate. The topic of exceptions vs assert has been dealt with before in general, but, as I try to explain here, I don't feel that any of those questions addresses my particular situation.
(**) I wrote this with my own words, trying to resume what I've read. Feel free to criticize this statement if you feel it does not reflect the majority's consensus.
assert() is a safeguard against programmer mistakes, while exceptions are safeguards against the rest of existence.
Let's explain this with an example:
double divide(double a, double b) {
return a / b;
}
The obvious problem of this function is that if b == 0, you'll get an error.
Now, let's assume this function is called with arguments which values are decided by you and only you. You can detect the problem by changing the function into this:
double divide(double a, double b) {
ASSERT(b != 0);
return a / b;
}
If you have accidentally made a mistake in your code so that b can take a 0 value, you're covered, and can fix the calling code, either by testing explicitely for 0, or to make sure such a condition never occurs in the first place.
As long as this assertion is in place, you will get some level of protection as the developer of the code.
It is a contract that makes it easy to see what kind of problem can occur in the function, especially while you are testing your code.
Now, what happens if you have no control over the values that are passed to the function ?
The assertion will just disrupt the flow of the program without any protection whatsoever.
The sensible thing to do is this:
double divide(double a, double b) {
ASSERT(b != 0);
if (b == 0)
throw DivideByZeroException();
return a / b;
}
try {
result = divide(num, user_val);
} catch (DivideByZeroException & e) {
display_informative_message_to_user(e);
}
Note that the assertion is still in place because it is the most readable indication of what can go wrong.
The addition of the exception, however, allows you to recover more easily from the problem.
It can be argued that such an approach is redundant, but in a release build, the assertions will usually be NOOPs without generated code, so the exception remains the sole protection.
Also, this function is very simple, so the assertion and the exception throw are immediately visible, but with a few dozens of lines of code added, that would not be the case anymore.
Now, when you are developing and likely to do mistakes, the assertion failure will be visible at exactly the line where it occured, while the exception might bubble up into an unrelated try/catch block that would make it harder to pintpoint the problem exactly, especially if the catch block does not log stack traces.
So, if you want to be safe and mitigate the risks of mistakes during development and during normal execution, you can never be too careful, and might want to provide both mechanisms in a complementary way.
I'm in a similar situation; engineering software, sole developer, very few users of my programs. My rule of thumb is to use exceptions when the program could feasibly recover from an error, or when a user should be expected to react to the error in some way. An example is checking for negative numbers where only positive numbers are allowed: the program doesn't need to terminate because the user typed in a negative value for mass, they just need to recheck their inputs and try again.
On the other hand, I use asserts to catch major bugs in the software. In the event that some error occurs from which the program has no hope of recovering (or that the user has no hope of fixing themselves), I just let the assert print out the file name and line number so that the user can report it to me, and I can fix it. An example of where I would use an assert is checking that the number of rows and columns of a matrix are equal when I'm expecting a square matrix. If num_rows != num_cols, then something is seriously broken with the code and some debugging is required. In my opinion, this is easier than trying to imagine all the possible ways that a matrix could become invalid, and test for them all.
As far as performance, I only disable or remove asserts and other error checks in critical sections of code, and then only when that section has been thoroughly tested and debugged.
My approach is probably not good for production software though. I can't imagine some program like Microsoft Excel bombing out with an "assertion failed" message. Ha ha. It's one thing if the three coworkers who use your software complain about your error-handling strategy, but quite another if you have thousands of unhappy customers who paid cash for it.
I'd use assertions where I expect the check to have a performance impact. I.e. when writing a vector or matrix class of simple types (e.g. double, complex<double>), and I wanted to make a bounds check I'd use assert(), because the check there has a potentially large performance impact, since it happens with every element access. I can then turn off this check in production builds with -DNDEBUG.
If the cost of the check does not matter (e.g. a check that an initial solution does not contain NaN values before you pass it to an iterative scheme), I would use an exception or another mechanism that is also active in production builds. If your job aborts after waiting in the queue of a cluster for three days and running for 10 hours, you at least want to have a diagnostic better than "killed (SIGSEGV)", so you can avoid rebuilding in debug-mode, waiting another 3 days and spending another 10 hours of expensive computation time.
The are situations where neither exceptions nor asserts are appropriate. An example would be an error where the cost of checking does not matter, but that is nevertheless fatal enough that the program cannot continue under any circumstances. An assertion is not appropriate, because it only triggers in debug mode, an exception is not appropriate, because it can (accidentally) be caught, obscuring the problem. In such a case I'd use a custom assert macro, that does not depend on NDEBUG, e.g.:
// This assert macro does not depend on the value of NDEBUG
#define assert_always(expr) \
do \
{ \
if(!(expr)) \
{ \
std::cerr << __FILE__ << ":" << __LINE__ << ": assert_always(" \
<< #expr << ") failed" << std::endl; \
std::abort(); \
} \
} while(false)
(This example was taken from here with a modified name to indicate the slightly broader purpose).
I had a disagreement with another programmer on how to write a method with a lot of error checking:
public void performAction() {
if (test1) {
if (test2) {
if (test3) {
// DO STUFF
} else {
return "error 3";
}
} else {
return "error 2";
}
} else {
return "error 1";
}
}
-
public void performAction() {
if (!test1) {
return "error 1";
}
if (!test2) {
return "error 1";
}
if (!test3) {
return "error 1";
}
// DO STUFF
}
To me, the deep nesting of if statements makes the first example hard to read.
The second one, despite having three returns, is more readable.
I checked by curiosity what Code Complete was saying about that and it left me less sure about the way to handle this:
The stack of error conditions at the bottom of the nest is a sign of well-written error-processing code.
but then
Indenting the main body of the routine inside four if statements is aesthetically ugly, especially if there’s much code inside the innermost if statement.
and considering using guard clauses, as in the second example
Minimize the number of returns in each routine. It’s harder to understand a routine when, reading it at the bottom, you’re unaware of the possibility that it returned some-where above.
How do you write the error checking part of a method to make it readable and error-prone?
Nothing gets programmers into a fight faster than stylistic debates (Is it ever advantageous to use 'goto' in a language that supports loops and functions? If so, why?). So the short answer is "Whatever style you and your team decide is best for your project/language."
That being said, I would like to add my 2 cents to Code Complete's comment about multiple returns. You should make a distinction between multiple successful returns, and multiple returns. If I need to investigate 5 returns that are not due to errors being generated, the function probably needs to be rewritten. If you gracefully exit your function immediately after an error is detected, then a maintenance programmer (i.e. you in 6 months) should have no more trouble following the main logic of your function than if you had nested all of those error checks.
So, my personal opinion is that your second code example is the better choice.
This is my opinion.
The old mantra of "Minimize the number of returns in each routine" seem to be a bit dated. It is highly applicable when you have methods longer 8-10 lines of code, where lots of operations are executed.
The newer schools of thought, emphasizing Single Responsibility and very short methods, would seem to render that a bit unnecessary. When your whole method does not do any operations directly, but simply handles the error processing, multiple returns in a clean format would be best.
In either case, any time you have nested ifs, the readable suffers substantially.
The one optimization I would make is to use an if-else-if structure, to clearly indicate the logic flow.
Sample code:
public void Execute()
{
if (test1)
{
return;
}
else if (test2)
{
return;
}
PerformAction();
}
private void PerformAction()
{
//DO STUFF
}
If you're using a language with exception-handling and automated resource management, your colleagues should probably get used to your preferred style with premature exits in the case of encountering a external input error.
The idea of trying to shift function exits towards the bottom of the scope was useful in the days before exception handling and automated resource management (ex: languages without destructors or GC like C) because error recovery often required manual cleanup.
In those manual cleanup cases, it was often useful to shift the exits towards the bottom of a function so that you could look at the top of the function for the logic creating the temporary resources needed by the function and towards the bottom of the function to see the symmetrical clean up of those resources.
In such cases as with assembly, it's quite common to see jumps/branches to an error label at the bottom of the function where the clean up would occur. It's also not too uncommon even in C using gotos for this purpose.
Also, as mentioned, deep nesting introduces a lot of mental overhead. Your brain has to function like a deeply-nested stack trying to remember where you're at, and as even Linus Torvalds, a diehard C coder, likes to say: if you need something like 4 nested levels of indentation in a single function, your code is already broken and should be refactored (I'm not sure I agree with him about the precise number, but he has a point in terms of how it obfuscates logic).
When you move into a more modern language like C++, you now have automated resource management via destructors. Functions should then no longer be mentioning cleanup details, as the resources should handle the cleanup automatically by conforming to what's called the resource acquisition is initialization idiom (not exactly the best name). That eliminates one of the big reasons to favor a style that strives to have error handling logic towards the bottom.
On top of that, when you use a language like C++, it potentially throws exceptions and all over the place. So it's not uncommon for every other line of code to have the effect of having a hidden, implicit exit with logic like this:
if an exception occurs:
automatically cleanup resources and propagate the error
So there are hidden, premature exits all over the place. So if you use a language like that, not only should you get used to premature exits in the case of an exception, but you're kind of forced into it and have no other choice. As far as readability/traceability is concerned in those languages, you can't get any simpler than:
if something bad happened:
return error
The one exception I'd suggest to the rule is static branch prediction. If you're writing very performance-critical code where the smallest of micro-efficiencies counts more than readability, then you want your branches to be weighted towards favoring the common case line of execution as Intel advises. So instead of:
if something exceptional happened:
return error
... for performance you might invert the logic and do this instead:
if something normal happened:
...
return success
return error
I am writing a C++ code that controls a special device that is the fusion of several SDKs. My code looks like
#define sdk1SafeCall(err) __sdk1SafeCall(err,__FILE__,__LINE__)
int errorcode = 0;
sdk1SafeCall(sdk1_InitializeDevice());
errorcode=sdk2_InitializeDevice();
errorcode=sdk3_InitializeDevice();
if (some_parameter)
{
errorcode=sdk2_readDevice(true);
}
else
{
errorcode=sdk3_writeDevice();
}
label again: errorcode=sdk1_readDevice();
if (error) goto again;
errorcode=close_everything();
Use parameters will rearrange the control flow. My current method uses something like cudaSafeCall to wrap the error codes and exit. What I don't know how to do is where to store detailed explanations of these errors or how to recover from them (such as the goto example). At the end of the day the code looks really messy.
Edit
I do sometimes handle errors with a wrapper.
Writing error-safe code is hard. In your pseudocode, you don't actually deal with errors at all. errorcode will just have the result of "close_everything()" - which may have succeeded, even if everything else went wrong.
The typical way to solve this sort of thing in C++ is to have an object for each "resource" (e.g. a "device"), and throw an exception if something goes wrong that you don't expect to recover from. Wrap the whole function [or an outer set of functions] in a try/catch block.
Of course, if "failure is normal" (e.g. you try to read from a network port, and you get a timeout because there was no data available, that's not something you should throw an exception for). This should use a return-value.
Note that using objects to handle resources requires careful design of the code and especially that your destructor does a good job of cleaning it is run after an exception. Make sure you don't leave things behind if you throw an exception in a constructor - as that is how you get leaks.
There are naturally a whole host of other solutions - after all, we're talking programming, so there's always at least 11 different ways to solve something.
I'm writing a reactive software, which repeatedly recieves input, processes it and emits relevant output. The main loop looks something like:
initialize();
while (true) {
Message msg,out;
recieve(msg);
process(msg,out);
//no global state is saved between loop iterations!
send(out);
}
I want that whatever error occured during the proccess phase, whetehr it is out of memory error, logical error, invalid assertion etc, the program will clean up whatever it did, and keep running. I'll assume it is invalid input, and simply ignore it.
C++'s exception are exceptionally good for that situation, I could surround process with try/catch clause, and throw exception whenever something goes wrog. The only thing I need to make sure that I clean up all my resources before throwing an exception. This could be verified by RAII, or by writing a global resource allocator (for instance, if your destructor might throw an exception), and use it exclusively for all resources.
Socket s = GlobalResourceHandler.manageSocket(new Socket());
...
try {
process(msg,out);
catch (...) {
GlobalResourceHandler.cleanUp();
}
However, using exception is forbidden in our coding standard (also in Google's C++ standard BTW), as a result all the code is compiled with exceptions off, and I believe nobody's going to change the way everything work just for my design problem.
Also, this is code for embedded platform, so the less C++ extra feature we use, the faster the code becomes, and the more portable it is.
Is there an alternative design I can consider?
update:
I appreciate everyones answer about idiotic code standard. The only thing I can say is, in big organizations you have to have strict and sometimes illogical rules, to make sure no idiot would come and make your good code unmaintainable. The standard is more about people than about technicalities. Yes, bad man can make every code a mess, but it's much worse if you give him extra tools for the task.
I'm still looking for a technical answer.
Coding these kind of services all day long I understand your problem. Although we do have exceptions within our code, we don't return them to the external libraries that invoke it, instead we have a simple 'tribool'.
enum ReturnCode
{
OK = 0, // OK (there is a reason for it to be 0)
KO, // An error occurred, wait for next message
FATAL // A critical error occurred, reboot
};
I must say FATAL is... exceptional. There isn't any code path in the application that returns it, apart from the initialization (can't do much if you're not initialized properly).
C++ here brings much with RAII, since it laughs multiple paths of return off and guarantees deterministic release of the objects it holds.
For the actual code checking, you can simply use some macros:
// Here is the reason for OK being 0 and KO and Fatal being something else
#define CHECK_RETURN(Expr) if (ReturnCode code = (Expr)) return code;
#define CHECK_BREAK(Expr) if (ReturnCode code = (Expr)) \
if (KO == code) break; else return code;
Then you can use them like so:
CHECK_RETURN( initialize() )
while(true)
{
Message msg,out;
CHECK_BREAK( receive(msg) )
CHECK_BREAK( process(msg,out) )
CHECK_BREAK( send(out) )
}
As noted, the real bummer is about constructors. You can't have "normal" constructors with such a situation.
Perhaps can you use boost::optional, if you can't, I would really suggest duplicating the functionality. Combine that with systemic factory functions in lieu of constructors and you're off to go:
boost::optional<MyObject> obj = MyObject::Build(1, 2, 3);
if (!obj) return KO;
obj->foo();
Looks much like a pointer, except that it's stack allocated and thus involves near zero overhead.
If you can't throw an exception, then the alternative is to return (or to return false or similar error code).
Whether you throw or return, you still use C++ deterministic destructors to release resources.
The one thing that you can't easily just 'return' from is a constructor. If you have an unrecoverable error in a constructor, then it's a good time to throw; but if you're not allowed to throw, then instead you must return, and in that case you need some other way to signal construction failure:
Have private constructors and static factory methods; have the factory method return null on construction failure; don't forget to check for a null return when you call a factory method
Have a "get_isConstructedOk()" property which you invoke after each constructor (and don't forget to invoke/check it on every newly-constructed object)
Implement 'two-stage' construction: in which you say that any code which might fail mustn't be in a constructor, and must instead be in a separate bool initialize() method that's called after the constructor (and don't forget to call initialize and don't forget to check its return value).
However, using exception is forbidden
in our coding standard (also in
Google's C++ standard BTW). Is there
an alternative design I can consider?
Short answer is no.
Long answer yes :). You can make all functions return an error code (similar to the implementation of Microsoft's COM platform.
The main disadvantages of this approach are:
you have to handle all exceptional cases explicitly
your code size increases dramatically
the code becomes more difficult to read.
Instead of:
initialize();
while (true) {
Message msg,out;
recieve(msg);
process(msg,out);
//no global state is saved between loop iterations!
send(out);
}
you have:
if( !succeedded( initialize() ) )
return SOME_ERROR;
while (true) {
Message msg,out;
if( !succeeded( RetVal rv = recieve(msg) ) )
{
SomeErrorHandler(rv);
break;
}
if( !succeeded( RetVal rv = process(msg,out) ) )
{
SomeErrorHandler(rv);
break;
}
//no global state is saved between loop iterations!
if( !succeeded( RetVal rv = send(out) ) )
{
SomeErrorHandler(rv);
break;
}
}
furthermore, the implementation all your functions will have to do the same: surround each function call with an if.
In the example above, you also have to decide if the rv value on each iteration constitutes an error for the current function and (eventually) return it directly from the while, or break the while on any error, and return the value.
In short, except for possibly using RAII in your code and templates (are you allowed to use them?), you end up close to "C code, using the C++ compiler".
Your code transforms each function from a two-liner into an eight-liner and so on. You can improve this with use of extra functions and #defined macros but macros have their own idiosyncrasies that you have to be really careful about.
In short, your coding standards are making your code unnecessarily longer, more error prone, harder to understand and more difficult to maintain.
This is a good case to present to whoever is in charge of the coding standards in your company :(
Edit: You can also implement this with signals but they are a bad replacement for exceptions: they do the same thing as exceptions, only they also disable RAII completely and make your code even less elegant and more error prone.
Just because using exceptions is forbidden in your current coding standards this does not mean that you should dismiss them out of hand for future problems you encounter such as this. It may the case that your current coding standards did not envisage such a scenario arising. If they did they would probably give you help as to what the alternative implementation would be.
This sounds to me like a good time to challenge your current coding standards. If the people that wrote them are still there then speak to them directly as they will either be able to answer your question as to alternative strategies or they will accept that this is a valid use-case for exceptions.
However, using exception is forbidden in our coding standard (also in Google's C++ standard BTW). Is there an alternative design I can consider?
Coding standards like that are nuts.
I suggest that you ask the person / people who developed and mandated that standard how to solve your problem. If they have no good answer, use this as justification for ignoring that part of the coding standard ... with your bosses permission of course.
If you are running under windows, you could use SEH exceptions. They also have the advantage of pre-stack-unwind handler which can stop unwind (EXCEPTION_CONTINUE_EXECUTION).
Off the top of my head, you might be able to achieve something similar with signals.
Set up a signal handler to catch appropriate signals and have it clean things up. For example, if your code generates a SIGSEGV as a result of something that would otherwise have thrown an exception a little earlier, you can try catching it with the signal handler.
There may be more to it than this as I have not thought it through.
Hope this helps.
Do you call any libraries that could raise exceptions? If it's the case, you will need a try catch anyway. For your internal errors, each method will need to return an error code (use return only for error code, use reference parameters to return the actual values). If you want to make memory cleanup 100% reliable, you could start your application using a monitor application. If your application crash, the monitor start it again. You still need to close files and DB connection, tho.
Another approach is, instead of throwing exception, set a global error indicator, and return a legal but arbitary input. Then checking in every loop iteration whether or not the global error indicator is set, and if it is - return.
If you're careful enough, you can make sure that returning legal data will never cause you to crash or to cause undefined behaviour. Thus you shouldn't care that the software will keep running a bit until it reaches to the nearest error checking condition.
For example
#define WHILE_R(cond,return_value) while (cond) {\
if (exception_thrown) return return_value
#define ENDWHILE() }
bool isPolyLegal(Poly p) {
PolyIter it(p);
WHILE_R(it.next(),true) //return value is arbitary
...
if (not_enough_memory) exception_thrown = true;
...
ENDWHILE()
}
I've programmed C and C++ for a long time and so far I've never used exceptions and try / catch. What are the benefits of using that instead of just having functions return error codes?
Possibly an obvious point - a developer can ignore (or not be aware of) your return status and go on blissfully unaware that something failed.
An exception needs to be acknowledged in some way - it can't be silently ignored without actively putting something in place to do so.
The advantage of exceptions are two fold:
They can't be ignored. You must deal with them at some level, or they will terminate your program. With error code, you must explicitly check for them, or they are lost.
They can be ignored. If an error can't be dealt with at one level, it will automatically bubble up to the next level, where it can be. Error codes must be explicitly passed up until they reach the level where it can be dealt with.
The advantage is that you don't have to check the error code after each potentially failing call. In order for this to work though, you need to combine it with RAII classes so that everything gets automatically cleaned up as the stack unwinds.
With error messages:
int DoSomeThings()
{
int error = 0;
HandleA hA;
error = CreateAObject(&ha);
if (error)
goto cleanUpFailedA;
HandleB hB;
error = CreateBObjectWithA(hA, &hB);
if (error)
goto cleanUpFailedB;
HandleC hC;
error = CreateCObjectWithA(hB, &hC);
if (error)
goto cleanUpFailedC;
...
cleanUpFailedC:
DeleteCObject(hC);
cleanUpFailedB:
DeleteBObject(hB);
cleanUpFailedA:
DeleteAObject(hA);
return error;
}
With Exceptions and RAII
void DoSomeThings()
{
RAIIHandleA hA = CreateAObject();
RAIIHandleB hB = CreateBObjectWithA(hA);
RAIIHandleC hC = CreateCObjectWithB(hB);
...
}
struct RAIIHandleA
{
HandleA Handle;
RAIIHandleA(HandleA handle) : Handle(handle) {}
~RAIIHandleA() { DeleteAObject(Handle); }
}
...
On first glance, the RAII/Exceptions version seems longer, until you realize that the cleanup code needs to be written only once (and there are ways to simplify that). But the second version of DoSomeThings is much clearer and maintainable.
DO NOT try and use exceptions in C++ without the RAII idiom, as you will leak resources and memory. All your cleanup needs to be done in destructors of stack-allocated objects.
I realize there are other ways to do the error code handling, but they all end up looking somewhat the same. If you drop the gotos, you end up repeating clean up code.
One point for error codes, is that they make it obvious where things can fail, and how they can fail. In the above code, you write it with the assumption that things are not going to fail (but if they do, you'll be protected by the RAII wrappers). But you end up paying less heed to where things can go wrong.
Exception handling is useful because it makes it easy to separate the error handling code from the code written to handle the function of the program. This makes reading and writing the code easier.
return an error code when an error condition is expected in some cases
throw an exception when an error condition is not expected in any cases
in the former case the caller of the function must check the error code for the expected failure; in the latter case the exception can be handled by any caller up the stack (or the default handler) as is appropriate
Aside from the other things that were mentioned, you can't return an error code from a constructor. Destructors either, but you should avoid throwing an exception from a destructor too.
I wrote a blog entry about this (Exceptions make for Elegant Code), which was subsequently published in Overload. I actually wrote this in response to something Joel said on the StackOverflow podcast!
Anyway, I strongly believe that exceptions are preferable to error codes in most circumstances. I find it really painful to use functions that return error codes: you have to check the error code after each call, which can disrupt the flow of the calling code. It also means you can't use overloaded operators as there is no way to signal the error.
The pain of checking error codes means that people often neglect to do so, thus rendering them completely pointless: at least you have to explicitly ignore exceptions with a catch statement.
The use of destructors in C++ and disposers in .NET to ensure that resources are correctly freed in the presence of exceptions can also greatly simplify code. In order to get the same level of protection with error codes you either need lots of if statements, lots of duplicated cleanup code, or goto calls to a common block of cleanup at the end of a function. None of these options are pleasant.
Here's a good explanation of EAFP ("Easier to Ask for Forgiveness than Permission."), which I think applies here even if it's a Python page in Wikipedia. Using exceptions leads to a more natural style of coding, IMO -- and in the opinion of many others, too.
When I used to teach C++, our standard explanation was that they allowed you to avoid tangling sunny-day and rainy-day scenarios. In other words, you could write a function as if everything would work ok, and catch the exception in the end.
Without exceptions, you would have to get a return value from each call and ensure that it is still legitimate.
A related benefit, of course, is that you don't "waste" your return value on exceptions (and thus allow methods that should be void to be void), and can also return errors from constructors and destructors.
Google's C++ Style Guide has a great, thorough analysis of the pros and cons of exception use in C++ code. It also indicates some of the larger questions you should be asking; i.e. do I intend to distribute my code to others (who may have difficulty integrating with an exception-enabled code base)?
Sometimes you really have to use an exception in order to flag an exceptional case. For example, if something goes wrong in a constructor and you find it makes sense to notify the caller about this then you have no choice but to throw an exception.
Another example: Sometimes there is no value your function can return to denote an error; any value the function may return denotes success.
int divide(int a, int b)
{
if( b == 0 )
// then what? no integer can be used for an error flag!
else
return a / b;
}
The fact that you have to acknowledge exceptions is correct but this can also be implemented using error structs.
You could create a base error class that checks in its dtor whether a certain method ( e.g. IsOk ) has been called. If not, you could log something and then exit, or throw an exception, or raise an assert, etc...
Just calling the IsOk on the error object without reacting to it, would then be the equivalent of writing catch( ... ) {}
Both statement would display the same lack of programmer good will.
The transport of the error code up to the correct level is a greater concern. You would basically have to make almost all methods return an error code for the sole reason of propagation.
But then again, a function or method should always be annotated with the exceptions it can generate. So basically you have to same problem, without an interface to support it.
As #Martin pointed out throwing exceptions forces the programmer to handle the error. For example, not checking return codes is one of the biggest sources of security holes in C programs. Exceptions make sure that you handle the error (hopefully) and provide some kind of recover path for your program. And if you choose to ignore an exception rather than introduce a security hole your program crashes.