Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm a professional C programmer and a hobbyist Obj-C programmer (OS X). Recently I've been tempted to expand into C++, because of its very rich syntax.

So far coding I haven't dealt much with exceptions. Objective-C has them, but Apple's policy is quite strict:

Important You should reserve the use of exceptions for programming or unexpected runtime errors such as out-of-bounds collection access, attempts to mutate immutable objects, sending an invalid message, and losing the connection to the window server.

C++ seems to prefer using exceptions more often. For example the wikipedia example on RAII throws an exception if a file can't be opened. Objective-C would return nil with an error sent by a out param. Notably, it seems std::ofstream can be set either way.

Here on programmers I've found several answers either proclaiming to use exceptions instead of error codes or to not use exceptions at all. The former seem more prevalent.

I haven't found anyone doing an objective study for C++. It seems to me that since pointers are rare, I'd have to go with internal error flags if I choose to avoid exceptions. Will it be too much bother to handle, or will it perhaps work even better than exceptions? A comparison of both cases would be the best answer.

Edit: Though not completely relevant, I probably should clarify what nil is. Technically it's the same as NULL, but the thing is, it's ok to send a message to nil. So you can do something like

NSError *err = nil;
id obj = [NSFileHandle fileHandleForReadingFromURL:myurl error:&err];

[obj retain];

even if the first call returned nil. And as you never do *obj in Obj-C, there's no risk of a NULL pointer dereference.

share|improve this question
    
Imho, it would be better if you'd show a piece of Objective C code how you work with errors there. It seems, people are talking about something different than you are asking. –  Gangnus Feb 8 '12 at 0:02
    
In a way I guess I am looking for justification for using exceptions. Since I have some idea of how they're implemented, I do know just how expensive they can be. But I guess if I can get a good enough argument for their use I'll go that way. –  Per Johansson Feb 8 '12 at 9:59
    
It seems, for C++ you need rather justification for not to use them. According to reactions here. –  Gangnus Feb 8 '12 at 10:06
2  
Perhaps, but so far there hasn't been anyone explaining why they're better (except compared to error codes). I don't like the concept of using exceptions for things that are not exceptional, but it's more instinctual than based on facts. –  Per Johansson Feb 8 '12 at 10:18
    
" I don't like...using exceptions for things that are not exceptional" - agreed. –  Gangnus Feb 8 '12 at 10:21

4 Answers 4

There is a lovely couple of chapters in Clean Code which talks about this very subject - minus the Apple point of view.

The basic idea is that you never return nil from your functions, because it:

  • Adds a lot of duplicated code
  • Makes a mess of your code - I.e.: It becomes harder to read
  • Can often result in nil-pointer errors - or access violations depending on your particular programming "religion"

The other accompanying idea is that you use exceptions because it helps to further reduce the clutter in your code, and rather than needing to create a series of error codes that eventually become difficult to track manage and maintain (particularly across multiple modules and platforms) and are a pain for your customers to decipher, you instead create meaningful messages that identify the exact nature of the problem, make debugging simpler, and can reduce your error handling code to something as simple as a basic try..catch statement.

Back in my COM development days, I had a project where every failure raised an exception, and each exception needed to use a unique error code id based on extending windows standard COM exceptions. It was a hold-over from an earlier project where error codes had been previously used, but the company wanted to go all object-oriented and jump on the COM-bandwagon without changing the way they did things too much. It only took 4 months for them to run out of error code numbers and fell to me to refactor large tracts of code to use exceptions instead. Better to save yourself the effort up front and just use exceptions judiciously.

share|improve this answer
    
Thanks, but I'm not considering returning NULL. Doesn't seem possible in the face of constructors anyway. Like I mentioned I'd probably have to use an error flag in the object. –  Per Johansson Feb 8 '12 at 9:56

Here's the thing: Because of C++'s unique history and flexibility, you can find someone proclaiming virtually any opinion about any feature that you'd like. However, in general, the more that what you're doing looks like C, the worse an idea it is.

One of the reasons that C++ is much looser when it comes to exceptions is that you can't exactly return nil whenever you feel like it. There's no such thing as nil in the vast majority of cases and types.

But here's the simple fact. Exceptions do their work automatically. When you throw an exception, RAII takes over and everything is handled by the compiler. When you use error codes, you have to remember to check them. This inherently makes exceptions significantly safer than error codes- they check themselves, as it were. In addition, they're more expressive. Throw an exception and you can get out a string telling you what the error is, and can even contain specific information, like "Bad parameter X which had value Y instead of Z". Get an error code of 0xDEADBEEF and what, exactly, went wrong? I sure hope the documentation is complete and up-to-date, and even if you get "Bad parameter", it's never going to tell you which parameter, what value it had, and what value it should have had. If you catch by reference, as well, they can be polymorphic. Finally, exceptions can be thrown from places where error codes never can, like constructors. And how about generic algorithms? How is std::for_each going to handle your error code? Pro-tip: It isn't.

Exceptions are vastly superior to error codes in every respect. The real question is in exceptions vs assertions.

Here's the thing. Nobody can know in advance what pre-conditions your program has for operating, what failure conditions are unusual, which can be checked for beforehand, and which are bugs. This generally means that you cannot decide beforehand whether a given failure should be an assertion or an exception without knowing the program logic. In addition, an operation which can continue when one of it's sub-operations fail is the exception, not the rule.

In my opinion, exceptions are there to be caught. Not necessarily immediately, but eventually. An exception is a problem that you expect the program to be able to recover from at some point. But the operation in question can never recover from a problem which warrants an exception.

Assertion failures are always fatal, unrecoverable errors. Memory corruption, that sort of thing.

So when you can't open a file, is it an assertion or exception? Well, in a generic library, then there are plenty of scenarios where the error can be handled, for example, loading a configuration file, you might simply use a pre-built default instead, so I'd say exception.

As a footnote, I'd like to mention there's some "Null Object Pattern" thing going around. This pattern is terrible. In ten years, it will be the next Singleton. The number of cases in which you can produce a suitable null object is miniscule.

share|improve this answer
    
The alternative isn't necessarily a simple int. I'd be more likely to use something akin to NSError which I'm used to from Obj-C. –  Per Johansson Feb 7 '12 at 23:57
    
He is comparing not to C, but to Objective C. It is a big difference. And his error codes are explaining lines. Al that you say is correct, only not answers on this question somehow. No offence meant. –  Gangnus Feb 7 '12 at 23:59

In the post that you reference, (exceptions vs error codes), I think there is a subtly different discussion going on. The question there seems to be whether you have some global list of #define error codes, probably complete with names like ERR001_FILE_NOT_WRITEABLE (or abbreviated, if you're unlucky). And, I think the main point in that thread is that if you're programming in a polymporphic language, using object instances, such a procedural construct is not necessary. Exceptions can express what error is occurring simply by virtue of their type, and they can encapsulate information like what message to print out (and other things as well). So, I'd take that conversation as one about whether you should program procedurally in an object oriented language or not.

But, the conversation of when and how much to rely on exceptions for handling situations that arise in code is a different one. When exceptions are thrown and caught, you are introducing a completely different control flow paradigm from the traditional call stack. Exception throwing is basically a goto statement that wrenches you out of your call stack and sends you to some indeterminate location (wherever your client code decides to handle your exception). This makes exception logic very hard to reason about.

And so, there is a sentiment like that expressed by jheriko that these should be minimized. That is, let's say that you're reading a file that may or may not exist on disk. Jheriko and Apple and those who think as they do (myself included) would argue that throwing an exception is not appropriate - the absence of that file is not exceptional, it's expected. Exceptions shouldn't substitute for normal control flow. It's just as easy to have your ReadFile() method return, say, a boolean, and to have client code see from the return value false that the file was not found. Client code can then tell the user file was not found, or quietly handle that case, or whatever it wants to do.

When you throw an exception, you're forcing a burden on your clients. You're giving them code that will, sometimes, wrench them out of the normal call stack and force them to write additional code to prevent their application from crashing. Such a powerful and jarring burden should only be forced on them if absolutely necessary at runtime, or in the interests of the "fail early" philosophy. So, in the former case, you can throw exceptions if the purpose of your application is to monitor some network operation and someone unplugs the network cable (you're signalling a catastrophic failure). In the latter case, you may throw an exception if your method expects a non-null parameter and you're handed null (you're signaling that you're being used inappropriately).

As for what to do instead of exceptions in the object-oriented world, you have options beyond the procedural error code construct. One that spring immediately to mind is that you can create objects called OperationResult or some such thing. A method can return an OperationResult and that object can have information about whether the operation succeeded or not, and whatever other information you want it to have (a status message, for example, but also, more subtly, it can encapsulate strategies for error recovery). Returning this instead of throwing an exception allows for polymorphism, preserves control flow, and makes debugging much simpler.

share|improve this answer
    
I agree with you, but it's the reason most seem not to that made me ask the question. –  Per Johansson Feb 8 '12 at 10:16

Exceptions were invented for a reason, which is to avoid having all your code look like this:

bool success = function1(&result1, &err);
if (!success) {
    error_handler(err);
    return;
}

success = function2(&result2, &err);
if (!success) {
    error_handler(err);
    return;
}

Instead, you get something that looks more like the following, with one exception handler way up in main or otherwise conveniently located:

result1 = function1();
result2 = function2();

Some people claim performance benefits to the no exception approach, but in my opinion readability concerns outweigh minor performance gains, especially when you include execution time for all the if (!success) boilerplate you have to sprinkle everywhere, or the risk of harder to debug segfaults if you don't include it, and considering the chances of exceptions happening are relatively rare.

I don't know why Apple discourages the use of exceptions. If they are trying to avoid propagating unhandled exceptions, all you really accomplish is people using null pointers to indicate exceptions instead, so a programmer mistake results in a null pointer exception instead of a much more useful file not found exception or whatever.

share|improve this answer
1  
This would make more sense if code without exceptions actually look like that, but it usually doesn't. This pattern appears when error_handler never returns, but seldom otherwise. –  Per Johansson Feb 8 '12 at 10:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.