Advertisement

Error Handling

Started by February 12, 2000 11:00 PM
31 comments, last by Daniel Benmergui 24 years, 7 months ago
Hello Everybody! This is the problem i have: I am making a 2D graphic library for a game i am doing. I have a set of classes that manage sprites, tilesets,etc. But i crashed when i had to come up with a solution to error handling... suppose this scheme: DirectDraw(COM)<-Sprite<-TileSet (these both are my classes) How should i handle the errors? I could only come up with two ways: 1) notify errors with return values The problem is that i would lose information about the errors...look at this DDraw(DDERR_INVALIDPARAMS)<-Sprite(SPRITEERR_DDRAWFAILED)<-Tileset(TILESETERR_SPRITEFAILED) My main program won''t know what happened, so debugging or recover is almost impossible. 2)Make an ErrorHandler class, and put a pointer to one in each class. So when a class finds an error, it would send an string to the ErrorHandler class like this Sprite(send("SPRITE: Direct Draw Failed!"))<-TileSet("Couldn''t draw tile") So when my main checks for errors it would fire a messagebox saying: "Couldn''t Draw -> SPRITE:Direct Draw Failed!" But none of these solutions seems good...any ideas? THANKS!!!!
I don''t know if it would be considered good or bad design, or if I really understand what you''re saying, but you could just handle the errors where they originate, instead of passing them down the chain of classes... Or is there some reason that wouldn''t work?

------------------------------
Jonathan Little
invader@hushmail.com
http://www.crosswinds.net/~uselessknowledge
Advertisement
Jonathan:

The problem is that there are some errors that the class that generates them don''t know what to do with them. For example, suppose that DirectDraw cant blit because it lost its surfaces...it is a recoverable error, so it shouldn''t break execution. But my main has to know what happened so it can restore the surface. With scheme 1, he would never know what happened, and scheme 2 looks inelegant.
Let''s put it this way...if you had a library structure like this:
DirectDraw (the DX COM ))
/\
Tile------>(position, rectangle of the surface)
/\
TileSet------>(Collection of Tiles)

What would you do to handle a LOSTSURFACE error in DD when you made Tileset.Render(lpBackBuffer)

Thanks!


One of the best ways in general to handle error situations like this (libraries encountering errors they don''t know how to handle) is exceptions. Many people don''t like exceptions, though, as they claim it involves a large amount of overhead. Technically, exceptions can be used such that they only generate any significant overhead when they happen, and the common (non-error) case is still fast. As for the exact details of the design, exception handling gives you TONS of flexibility in passing error information back up the stack, and correcting problems when they occur. It ends up being similar to your second idea, but (at least in my view) much cleaner.

-Brian
I will research more about exceptions to see if they solve the problem...however, i am afraid it could be a problem of bad design...
Thanks Brian
Yes, exceptions are a perfect tool. Any other decision will work with good design too, but exceptions are the best way to handle errors IMO. I use them almost always, except when
program is really small (under aprox. 500 LOC).


For example, u can use it this way:

quote:
try
{
if (InitApplication (instance, command_show) != TRUE)
return FALSE;
while (TRUE)
{
if (PeekMessage (&message, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage (&message, NULL, 0, 0))
return message.wParam;
TranslateMessage (&message);
DispatchMessage (&message);
}
else if (aplication_status)
{
//main game loop
if (!game.GameMain ())
{
game.ShutDown ();
break;
}
}
else
{
WaitMessage();
}
} //while (TRUE)
} //try

//catching errors here
catch (Error error)
{
ShowCursor (TRUE);
//show error on screen
ErrorToMsgBox (error.GetText ());
//dump to error file in if #define set
#ifdef DUMP_ERROR_TO_FILE
ErrorToFile (error.GetText ());
#endif // #ifdef DUMP_ERROR_TO_FILE
ShutDownSystem ();
} //catch (Error error)
return FALSE;



Sorry for indents in this example, I can not
figure out how to use indents with this board.
Any ideas?

You will need error handling class, which you will
throw in case of error and to which you will pass
error information.

For good information about error handling check
here:

"The C++ programming Language" Third Edition,
Bjarne Stroustrup, ISBN 0-201-88954-4



Fariz Alikishibekov,
fariz@warriormage.com
www.warriormage.com

Edited by - Fariz on 2/13/00 12:21:13 AM
Fariz Alikishibekov, www.warriormage.com
Advertisement
Yeah, sorry about that. I didn''t think of that, but exceptions would probably be perfect.
"You will need error handling class, which you will
throw in case of error and to which you will pass
error information."

You can throw any kind of variables (integers, structs, whatever). Also, while im at it, using catch(...) can be pretty useful as this will catch all unhandeled exceptions. ie:

try
{
...
}
catch(CError& error)
{
...
}
catch(...)
{
// caught unhandeled exception
...
}
It may be that I failed to understand the error, but it might seem like you are letting the error ripple too much far above. Error should not ripple too far above, if it does, it most likely smell like a bad design. Can''t blt due to lost surface? restore and blt again in the same function call! If it fails, well, it would also fail if it is handled above. So you can safely throw an exception or return an error value saying just failure.
Exception handling is the way to go if your going to be using c++. However, be sure to wrap each COM interface in a seperate class. Aqurie the resource in the constructor and release it in the destructor. Throwing an exception will cause the program to start backing out of scopes untill it reaches the first catch block. As excution leaves each scope, destructors for each variable declared in that scope will be invoked. Any COM interfaces you''ve aquired or memory you''ve allocated will not be freed unless they are released in destructors.
- Ryan -

This topic is closed to new replies.

Advertisement