Jump to content
  • Advertisement
Sign in to follow this  
3dmodelerguy

When To And Not To Use Exceptions?

This topic is 2638 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Something that I have always had a hard time understanding because there seems to be a lot of people on both side of this discussion is when to use an exception and when not too. Here is a real world example from PHP (but the concept is the same in any language). Lets say I have a method that takes a string that should have a valid date time readable format and then converts that date time from one timezone to another timezone. Now something that is entirely possible is that the string that is passed in might not be a valid date time readable string as we don't know the source of that string. Multiple people have told to me just return null, false, etc... because it is excepted that the string passed in might not be in a date time readable format however it seems like throwing an exception of UnreableDateTimeString would seem like a much better option. Throwing this exception would let the code know exactly what went wrong and therefore know how exactly to fix it.

I guess I am curious on how someone would would handle a method return null but having multiple reason on why it was returned null. If you throw exceptions, you can throw different types of exceptions which would allow your code to handle the different reasons the method failed differently very easily. Is it really bad to throw exceptions in cases like these? What is a case where you really don't want to throw and exception (the only place I can think of is form validation even though I could see a case for exceptions here).

Share this post


Link to post
Share on other sites
Advertisement
Exceptions are not the same in every language or even every language implementation. There are some platforms where you never want to even enable exceptions because the compiler support for them are just that bad, for example some C++ compilers for consoles. In any case, if you have a function that has only a single failure return value, but multiple failure reasons you can store extended information somewhere else. This is the basic idea behind the GetLastError() function used by the Windows API or the errno variable used by the C standard library.

Share this post


Link to post
Share on other sites
This most certainly depends on your language.

In C++, for instance, it can be very tricky and subtly difficult to get exception safety from your code - i.e. a guarantee that no matter when an exception is thrown, you won't leak resources or cause the program to enter an invalid state. By contrast, in languages like C# and Java, exception safety is slightly easier and using exceptions is more or less the norm.

PHP has so many ugly corner cases and weird quirks that I can't even begin to speculate on what qualifies as good practice in that language; I'm too scared to use it for anything non-trivial, so I don't know what it feels like to work on seriously-engineered codebases in PHP - if such a thing even exists.

Sometimes you just don't have a choice: C has no exceptions, for instance.

And sometimes you have better options, such as continuation-passing style in certain functional languages.


So really if you're interested in solid reasoning for or against exceptions, it'd help to narrow it down to a particular language. If your language is C++, be sure to specify a compiler and target OS, because as SiCrane noted that can make a huge difference.

Share this post


Link to post
Share on other sites
(Java based)
You've kind of answered your own question a little bit. Exceptions are more advanced error handling, for example if multiple things can go wrong and you want to react differently to each problem.


In most simple circumstances and .Get() Operations returning a null type is preferable because its faster and easier.


// The function throwing a null type
function getSomething() {
if(something != null) {
return something
}
else {
return null
}
}

// The function calling and handling it
if(getSomething != null) {
// Do something with something
}
else { // something is null
// Resolve the problem or just skip over it.
}

Share this post


Link to post
Share on other sites
Maybe it's not the case any more, but some years ago when I last looked into it, throwing an exception and having it caught was much slower than simply returning null, false etc. Using exceptions is then great for catching truly abnormal situations, but if the value being passed to a function can legitimately be in an odd state, then handling it within the function (or even better, by the caller) may prove much faster.

Our problem was in a tight loop - a function had been throwing an exception when returning false would have sufficed - and the program slowed down to a crawl.

As to other ways of returning a result - return an enumerated result?
if (SUCCESS == function(x)) { ...
or check the value before passing it?
if (IsValid(x)) function(x);

It's hard to see how either would be slower than throwing an exception. But then, if (x) should always be valid, then throwing an exception seems completely legitimate. It is, after all, an exception...

Share this post


Link to post
Share on other sites
Even though I use C#, I try to avoid Exceptions wherever possible. I find them to be a "messy" way of handling error conditions. I much prefer to return an integer representing some sort of error condition, or null depending on the context and then handle that condition in the calling function. (You should always be sanity checking your return values anyway.)

If I recall correctly, Exceptions trigger all kinds of black magic in the CPU, which can be quite slow if exceptions are continuously being thrown in a loop for example. In either case, its much better to return a null or something from the function and test the value in my opinion.

Share this post


Link to post
Share on other sites
Regardless of language you should only use exceptions for things that shouldn't happen unless something is really wrong, File IO, Parsing of scripts or other resources, etc are good candidates for using exceptions, If you fail to execute the AI script (due to a syntax error in the script for example) for an enemy it really doesn't matter if throwing an exception is slow, you're screwed anyway and you need alot more information than you can get from a single return value, the only real alternative to exceptions then is to use getLastError style functions to retrieve additional error information (Which imo are quite ugly and can have its own set of problems in multithreaded applications)

Share this post


Link to post
Share on other sites

Regardless of language you should only use exceptions for things that shouldn't happen unless something is really wrong,

Not really, this is still language dependent. Python, for example, has very cheap exceptions so it's entirely reasonable to use exceptions to report "regular" error conditions. For example, parsing an int from a string with int() is something that throws an exception rather than return and that's something that can happen easily during normal execution.

Share this post


Link to post
Share on other sites

EDIT: My initial response was an explanation of why many game studios have historically decided not to use exceptions. It essentially boiled down to:

  • O.P.'s question can be tricky to answer.
  • Exception safety can be sticky business.

This, of course, doesn't answer O.P.s question at all, and seems to have sparked a bizarre, somewhat nonsensical debate. So I'm retracting it, and instead offering this link to what the experts have to say on this topic. I'll even refrain from summarizing the article for fear of more meaningless debate.

Edited by vreality

Share this post


Link to post
Share on other sites
You're setting up error code handling and exception handling for different standards.


The more serious problem is that it's non-trivial to make code 'safe' to use in the presence of exceptions. That is, special care must be taken to assure that the occurrence of an exception doesn't cause code to leave objects in unexpected or invalid states. This “special care” is problematic:

Exceptions are no more problematic than error codes. If you leave objects in invalid states with error codes, you might as well leave them invalid with exceptions. You don't have to handle it.



It's extremely code intrusive.


It's often complained that other approaches to error handling are code intrusive, and that's true. But exceptions are far more intrusive, and in a much more insidious way.

For example, in order for a member function to modify its object in an exception safe manner, it must either make all function calls (which could potentially throw exceptions) first, without changing the state of the object, then use the results to change the object state in ways that are somehow guaranteed not to allow exceptions, or it must catch all possible exceptions that can happen during the change of state, and then reliably restore the object to a valid state, without the possibility of causing any new exceptions in the meantime.

And with error codes you have to do the same, and more, if you want to leave the object in valid state. Or you can leave it in invalid state if you're not handling the error and will be shutting down anyway.


The latter approach is ad hoc, and can't be proven valid. The former approach is complicated by the way language syntax likes to hide function calls. But what's worse, is that it invisibly inserts exception safety coding decisions into just about every line of code written. Any maintenance geared toward the actual functionality of a piece of code is liable to break exception safety just as invisibly. Exception sanitized code will often appear nonsensical, and the only way to try to protect it from being “fixed” (broken, actually) is through a constant barrage of comments about exception safety.

Same can be said about error codes.


In other words, exception safety is a constant intrusion into nearly every line of code written.

So are error codes, you are checking them every line, right?


It's also design intrusive.

For example, if you had a “Stack” class with a “Pop” function that returned the item popped off the stack, theoretically, an exception could be thrown during the copy of the object that gets returned. This means that the stack would have lost the object (having already successfully “popped” it), but the client code would not yet have stored it, which may well represent an invalid program state.

So to allow the clients of a stack class to operate in an exception safe manner, “Pop” and “Get” functionality must be implemented separately. That is, “Pop”, which alters the stack, must not return an item, and “Get”, which returns an item, must not alter the stack.

Exception safety forces design decisions that appear odd and arbitrary. At best this can be confusing and annoying. Much worse is the likelihood that someone will “fix” the design, unknowingly making it “unsafe”.

Can this same be done more elegantly with error codes then?

While we welcome geniuses to our team, the fact is, we have better problems to be solving than exception-proofing code.

Besides, most of these errors, which we'd have to bend over backwards to allow “safely”, are ultimately fatal conditions to our application. By the time they happen, something has already gone wrong enough to prevent the correct function of the program.

It seems our best response to such errors is to trip a debugger break immediately, as near to the cause as possible, so we can diagnose and fix the problem, and ultimately produce code which will no longer result in a fatal condition. In other words, we find the “handling” of most exceptions to be counter-productive, and the all-pervasive labor, of making code “safe” for errors, to be irrelevant.

So if you're not handling errors anyway, I'm a bit confused why you talk so much about exception safety and handling them. Just throw and catch at top level to inform the user?


In addition to the above, unless exception handling is completely disabled for a build, the program must always perform exception handling bookkeeping behind the scenes for every function call ever made.

I think there are zero-overhead exception handling in some compilers, if no exception is thrown.

I think you're trying to do different things with exceptions and error codes. If you want to compare them, do the same thing. I find the reasons about some compilers not supporting them much better.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!