Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Every time I consider making my code strongly exception safe, I justify not doing it because it would be so time consuming. Consider this relatively simple snippet:

Level::Entity* entity = new Level::Entity();
entity->id = GetNextId();
entity->AddComponent(new Component::Position(x, y));
entity->AddComponent(new Component::Movement());
entity->AddComponent(new Component::Render());
allEntities.push_back(entity); // std::vector
entityById[entity->id] = entity; // std::map
return entity;

To implement a basic exception guarantee, I could use a scoped pointer on the new calls. This would prevent memory leaks if any of the calls were to throw an exception.

However, let's say I want to implement a strong exception guarantee. At the least, I would need to implement a shared pointer for my containers (I'm not using Boost), a nothrow Entity::Swap for adding the components atomically, and some sort of idiom for atomically adding to both the Vector and Map. Not only would these be time consuming to implement, but they would be expensive since it involves a lot more copying than the exception unsafe solution.

Ultimately, it feels to me like that time spent doing all of that wouldn't be justified just so that the a simple CreateEntity function is strongly exception safe. I probably just want the game to display an error and close at that point anyway.

How far do you take this in your own game projects? Is it generally acceptable to write exception unsafe code for a program that can just crash when there is an exception?

share|improve this question
19  
When I worked on C++ projects in the past, basically we pretended exceptions didn't exist. –  Tetrad Jan 13 '12 at 21:35
2  
I, personally, love exceptions and often actually enjoy figuring out how to make my code provide strong guarantees. If you're just going to crash when you get an exception though... maybe don't bother with it. –  Josh Petrie Jan 13 '12 at 22:19
7  
I personally use exceptions to manage.. hm.. 'exceptions' not errors. Like, if i know that a function may crash, i let it crash, but if i know that a function may not successfully read an archive, but there's another way, i surround it with a try, catch. and if its a "unable to read" exception, i just manage it the other way i would do without the archive reading. –  Gustavo Maciel Jan 13 '12 at 22:20
    
What Gtoknu said, you do need to be aware of which exceptions any external librares can throw. –  Psykocyber Jan 13 '12 at 22:24
    
Related: gamedev.stackexchange.com/questions/2762/… –  Tetrad Jan 14 '12 at 0:58

7 Answers 7

up vote 24 down vote accepted

If you're going to use exceptions (which isn't to say you should, there are pros and cons to that approach that are outside the specific scope of this question), you should write properly exception safe code.

Code that does not use exceptions and is explicitly not exception safe is better than code that uses them but is half-assing its exception safety. If you have the latter case, you have a whole class of bugs and failures that can occur when an exception happens that you probably cannot recover from at all, rendering one of the benefits of exceptions entirely null and void. Even if its a relatively rare class of failure, it's still possible.

This isn't to say that if you use exceptions, all code must provide the strong exception guarantee -- just that each piece of code should provide a guarantee of some sort (none, basic, strong) so that in the consumption of that code you know which guarantees you the consumer can provide. Generally the lower-level the component in question, the stronger the guarantee should be.

If you're never going to provide a strong guarantee or never going to really embrace the exception handling paradigms and all the extra work and disadvantages that implies, you also won't really be getting all the advantages it implies and you might have an easier time just forgoing exceptions altogether.

share|improve this answer
11  
This alone is worth a +1: "Code that does not use exceptions and is explicitly not exception safe is better than code that uses them but is half-assing its exception safety." –  Darth Satan Jan 14 '12 at 1:23

My general rule of thumb: If you need to use exceptions, use exceptions. If you don't need to use exceptions, don't use exceptions. If you don't know whether or not you need to use exceptions, you don't need to use exceptions.

Exceptions are there to be your absolute last line of defence in always-on mission-critical applications. If you're writing air traffic control software that absolutely cannot ever fail, use exceptions. If you're writing control code for a nuclear power plant, use exceptions.

When developing a game, on the other hand, you're much better off following the mantra: Crash early, crash loudly. If there's a problem, you really want to know about it as soon as possible; you don't ever want errors to be invisibly 'handled', because this will often conceal the actual cause of later misbehaviours and make debugging much more difficult than it needs to be.

share|improve this answer

The problem with exceptions is you have to deal with them anyway. If you getting an exception because your out of memory then it might be possible that you will be unable to handle that error anyway. Might as well just dump the entire game in 1 giant exception handler that pops up an error box.

For game development I prefer to try and find ways to make my code graciously continue with failures when possible.

For example I will hard code a special ERROR mesh into my game. It's a rotating red circle with a white X on it and a white border. Depending on the game an invisible one might be better. It has one singleton instance initialized on start. Since it's baked into the code rather than using any external files it shouldn't be possible to fail.

In the event a normal loadMesh call fails instead of throwing back some error and crashing to desktop it will silently log the failure to the console/logfile and return the hardcoded error mesh. I found out that Skyrim actually does the same thing when a mod screwed things up. There's a good possibility that the player wont even see the error mesh (unless there's some major problem and many of them are like it).

There's a fallback shader too. One that does basic vertex matrix operations but if there no uniform matrix for some reason it should still do the orthogonal view. It has no proper shading/lighting/materials (although it does have a color_overide flag so I can use it with my error mesh).

The only possible issue is if the error mesh version might permanently break the game in some way. For example ensure that it doesn't apply physics since if the player loads an area, then the error mesh kicks in it might fall to the floor then if they reload the game this time with the correct mesh working, if it's bigger it might be embedded in the ground. That shouldn't be too hard since your probably going to store your physics meshes with your graphical ones. Scripting might also be a problem. With some stuff you will just have to hard die. Not really sure what use a fall back 'level' would be (although you could make a small room with a sign saying there was a error, just make sure the save is disabled since you don't want the player stuck in it). Instances of fall back objects/components would be more problematic since they need to be unique but you can still have a special position that sets things to (0.0, 0.0, 0.0) or (-1000000.0, -1000000.0, -1000000.0) but once again you have to ensure it wont be saved or anything.

In the case of 'new', for game development it might be better to look at using some kind of a factory. It can give you various other advantages like preallocating objects before you actually need them and/or making them in bulk. It also makes it easier to make things like a global index of objects that you can use for memory management, finding things by an id, (although you can do that in constructors too). And of course you can handle allocation errors there too.

share|improve this answer

The big thing about missing runtime checks and crashes is the potential for a hacker to use a crash to take over the process and perhaps subsequently the machine.

Now, a hacker can't exploit an actual crash, as soon as the crash happens the process is useless and harmless. If you simply read from a null pointer it is a clean crash, you make a mistake and the process die instantly.

The danger comes when you execute a command that is not technically illegal, but wasn't what you intended to do, then a hacker might be able to direct that action using carefully crafted data that should otherwise be safe.

An uncaught exception isn't actually a real crash, it is just a way to terminate the program. Exceptions only happen because someone wrote a library that specifically throws an exception given certain circumstances. Typically to avoid going into an unexpected situation, which might be an opening for a hacker.

Actually, the dangerous move is to catch exceptions rather than letting them slip, that is not to say that you should never do so, but be sure that you only catch those you know you can handle and let the rest slip. Otherwise you risk undoing the safety measure carefully put into your library.

Focus on the errors that do not necessarily throw exceptions, like writing beyond the end of an array. Your program wouldn't by chance be able to do that?

share|improve this answer

You need to look at your exceptions and need to look at the conditions that can trigger them. A hell of a lot of time, a large percentage of what people use exceptions for can be avoided by proper checks during the development/debug build/testing cycle. Use asserts, pass references, always initialize local variables on declaration, memset-zero all allocations, NULL after free, etc, and an awful lot of theoretical exception cases just go away.

Consider: if something fails and may be a candidate for throwing an exception - what is the impact? How much does it matter? If you fail a memory allocation in a game (to take your original example) you generally have a bigger problem on your hands than how you handle the failure case, and handling the failure case by means of an exception won't make that bigger problem go away. Worse - it may actually hide the fact that the bigger problem is even there. Do you want that? I know I don't. I know that if I fail a memory allocation I want to crash and burn horribly and do so as close to the point of failure as possible, so that I can break into the debugger, figure what's going on, and fix it properly.

share|improve this answer

Not sure if quoting someone else is appropriate on SE but I feel none of the other answers really touched upon this.

Quoting Jason Gregory from his book Game Engine Architecture. (GREAT BOOK!)

"Structured exception handling (SEH) adds a lot of overhead to program. Every stack frame must be augmented to contain additional information required by the stack unwinding process. Also, the stack unwind is usually very slow-- on the order of two to three times more expensive than simply returning from the function. Also, if even one function in your program (or library) uses SEH, your entire program must use SEH. The compiler can't know which functions might be above you on the call stack when you throw an exception."

With that being said, my engine I'm building doesn't use exceptions. This is because of the before mentioned potential performance cost and the fact that for all my purposes error return codes work fine. The only time I really need to look for failures is in initializing and loading resources and in those cases returning a boolean indicating success works fine.

share|improve this answer
2  
Structured exception handling is a specific type of exception handling available on Windows, which isn't the same as C++ exceptions generally. –  Kylotan Jan 14 '12 at 17:57
    
Doh, I can't believe I didn't know this. Thanks for the correction! –  KlashnikovKid Jan 14 '12 at 20:13

I always make my code exception safe, simply because it makes it easier to know where problems arise, since I can log something whenever a exception is generated or caught.

share|improve this answer

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.