Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
88 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

  Contents

 Introduction
 Error Handling
 Win32 Skeleton
 Message Handler
 Conclusion

 Source code
 Printable version

 


  The Series

 Part I
 Part II

 

Error Handling

Before we start on our Win32 skeleton we should create some kind of error visualization system. Since using GDI (graphical device interface) to display text in DirectX isn't very fast, we're going to make have our error routine log errors in a text file instead. We will also add an option to exit the game when an error occurs. We'll create the class CError to handle all error routines. The prototype for our class will be the following:

class CError { public: FILE *fErrorLog; bool bQuit; LPSTR lpzMessage; CError (LPSTR, bool); ~CError (); ProcessError (DWORD); };

Now for a brief explanation of each variable. fErrorLog is a pointer to the file where we will log all our errors. bQbuit is just a Boolean variable holding true or false to indicate whether the program should quit or not when an error occurs. lpzMessage is the actual error message. The size of the message will be dynamically allocated when an error occurs for best performance in terms of memory and customizability (that sounded weird). CError is the constructor for the class; it takes a string and a boolean as arguments. The string is the name of the file where the errors will be logged and the boolean sets whether or not the program will quit when an error occurs. The destructor will clean things up when we're done.

For the C programmers, a class is just like a struct with functions; they have more advanced features as well, but we will not use them. Just in case you don't know, a constructor is called when an instance of the class is declared and the destructor is called when the instance is killed, either by the program termination, the variable going out of scope, etc.

We will now start the actual code for the error handling routines. First we must code the constructor and destructor.

CError::CError (LPSTR lpzFileName, bool bQuitOnError) { fErrorLog = fopen (lpzFileName, "wt"); bQuit = bQuitOnError; } CError::~CError () { }

The constructor is very straightforward; it only opens a file for writing in text mode using the filename specified by the first argument, and sets the quit flag to the value of the second argument.

The destructor is empty for now.

Next is the main core of our error handling. It's very basic for now, but it will grow as we start adding the errors for DirectX.

CError::ProcessError (DWORD dwError) { DWORD dwMsgSize; switch (dwError) { default : dwMsgSize = strlen ("Unkown error…\n"); lpzMessage = (LPSTR) malloc (dwMsgSize + 1); strcpy (lpzMessage, "Unkown error…\n"); break; } if (fErrorLog != NULL) { fprintf (fErrorLog, lpzMessage); } if (lpzMessage != NULL) { free (lpzMessage); } if (bQuit == true) { if (fErrorLog != NULL) { fclose (fErrorLog); } PostQuitMessage (dwError); } return 0; }

Let's look at this code more closely. We first declare a variable to hold the length of the string; after that we use the switch statement to find out which error we're handling. Right now, only the default is used, and it does three things: it checks the length of the string, allocates sufficient memory for it, and copies it to the string member of our class, lpzMessage. We then check to see if the error should be logged to the file and write it as needed. We then free the memory allocated to the string, and finally we check the bQuit flag to see if we should abort the program and close the file (after checking to see if the file is open).

I just want to add two comments about this function. First, whenever we want to add another error we should put the code before the default case; we will do this later. Second, we don't do any checking to see if all went well with the error handling. This is your homework. Check to see if the memory is allocated correctly, if the file was opened successfully, etc. Try to do this on your own, and if you can't then e-mail me and I'll help you out. I'll also post the corrections in the next article.

We will now need an instance of the class.

CError ErrorHandling ("errors.log", true);

And that's about it for error handling J. Now let's move on to the world of Windows.




Next : The Win32 Skeleton