Jump to content
  • Advertisement
Sign in to follow this  
bluemoon

Engine Error Handling

This topic is 4853 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

Hi @ all Currently I am working on a little game engine - so I am probably going to ask a few more questions the next time. :) When it comes to error handling I want my errors to be displayed on a console. So I want every Object that creates an error to write a small error string to a Stringlist which can be displayed by a console. The problem I have is: How or Where do I set the pointer to the stringlist ? Making this stringlist global is not a good idea. Is this being done by passing a pointer to the list through the constructor or a method or is there another nice way ?

Share this post


Link to post
Share on other sites
Advertisement
How about having an InternalErrorLog class? Perhaps make it completely static:

class InternalErrorLog
{
public:
static void AddError(const string& error);
static std::list<string>::iterator& GetLastError(); // Returns the iterator to the last error, so you can display the x last errors in your console.
private:
static std::list<string> m_errors;
}



Toolmaker

Share this post


Link to post
Share on other sites
I would use a Singleton for this. This way you don't have to pass around a bunch of pointers, and it will reduce the length of your constructors.

Then for instance if you want to display an error code, you may use something like ... ErrorHandler::toConsole("Blah blah").

Share this post


Link to post
Share on other sites
Whatever you do, don't simply make a global pointer/reference to an object. It should be hidden by a function call. If/when you start doing a multithreaded implementation, you need to have a function call there so you can strap on a mutex. Anyway, my implementation is pretty much a set of global get/set functions wrapping over a stream pointer. I'm not entirely happy with it, and I'll probably revise it later on.

Share this post


Link to post
Share on other sites
To do it without global variables, you pass a reference to the error handler to each object. When the object encounters an error, it does something like m_errorHandler.DisplayError( "..." );

Share this post


Link to post
Share on other sites
I have currently in my engine several forms of "errors."

First we have errors that are accidental, such as attempting to call a function through a null pointer (sure, you could check for null pointers, but lets assume the programmer is human and forgot), or pretty much anything that throws an exception. These I handle by building a string of values passed into my guard macros which identify where in the stack the error has occoured, which really helps find the error. This string is presented in win32 dialog, along with some system specs and such for bug reports.

Next, we have assertions. A program assumes certain things about its variables sometimes, perhaps that they should always be within a certain range, and getting outside of that range is "impossible." Other assumptions could be null references, or whatever you think should NEVER happen. These can be handled differently, but I chose a method that works for me. In debug builds, these are handled similarly to the errors above, with the stack unwind, but also the line and file of the assertion, as well as the actual code that causes the error are presented in a win32 dialog. In release builds, some assertions are removed, and the check is never executed.

Secondly, we have things I call "uh ohs." Something got a bit out of whack, but it's not the end of the world. Generally we just like to make note of these, so they can be addressed in due time. These are handled by logging a warning message into the log, but the app continues its execution.

I can provide a bit more info on any of these, if anyone is interested. It really isnt that fancy. ;)

Share this post


Link to post
Share on other sites
In games, there really aren't many errors that are recoverable. If the character's texture is missing, you really can't play, because you can't see the what character's like -- you certainly wouldn't want to ship like that!

Thus, I think that errors should either be treated as runtime errors (controller disconnected, need to re-connect) that are "normal events" that trigger special GUI, or they are pretty much stopping conditions. Thus, for stopping errors, throwing an exception, and having some high-level part of the game (perhaps the main game loop) catch and display the error is the right choice.

Logging errors to a console just means that the errors will be ignored (because they can) and you'll ship a game full of bugs.

Share this post


Link to post
Share on other sites
I'm sure to be roasted alive for this, but I make mine global.

"oh you should use a singleton!"

No, I want various ways to report errors. Some things are log worthy, some things are simply informative to the console. And I'm slightly stubborn :D

I created an interface [c++ pure virtual] whose only member is a function which takes a string. Declare a global pointer to it, and by default initialize it with a logging structure which does nothing. More specialized areas can create their own interfaces if needs be, or apps can create multiple instances.

The various parts of the app only then need to include the simple interface header, and they'll send logging to whatever the default is for the app. Loggers can then be inherited from the base interface to print to screen, print to file, print to a gui console, pop up a message box...

It's simple, it's extensible, it can be changed at runtime and it's damn near guaranteed to work. An important feature for a debugging utility.

Share this post


Link to post
Share on other sites
Agreed!

Actually, my stack unwind trick is a global char* initialized to a length of 4096. Pretty much what happens is you pass the guard macros a chunk of text, and it basically implements a try blcok and that text as a string variable inside of the try block. IF an error occours and an exception is thrown, the other macro (cleverly named unguard) will catch the error, and pass the newly created string into a function which uses some not-so-fancy pointer arithmetic to copy the strings in reverse order and rethrow the exception. The application is then responsible for catching the final error and calls another engine level function, which is what creates and displays the dialog box, and then the app does its cleanup and exit.

I might not be the most elegant, due to the global string, but it works perfectly, and doesnt involve a lot of global pointers, or creating classes to handle the errors or a bunch of nonsense, just simple strings are good enough for me.

Share this post


Link to post
Share on other sites
It might not be the most elegant due to char *'s, pointer arithmetic, and macros too...

Though something like that I hear is something that UT developers use a bit.

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!