It is currently Mon May 29, 2017 8:18 pm

All times are UTC - 5 hours




 Page 1 of 2 [ 36 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Created by camtasia??
PostPosted: Tue Aug 29, 2006 6:59 am 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
A class is created to handle all errors that may be generated in the game engine. All errors can be written to a file and displayed to the screen.


Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Fri Sep 01, 2006 11:42 am 

Joined: Sun Feb 11, 2007 10:04 am
Posts: 16
I am not with the video yet, but it says something with...
<code>
// Create a new log file.
FILE *fp;
fp = fopen(m_szFilename, "wt");
</code>
I don't know what the FILE may mean... Can you clear that up for me please? I am working still with this video, there is alot of functions and the way you use them. sprintf, _strdata, _strtime... I believe you could have explained how these is used with the % and the s n thingies you put right in the middle of the string.

I am having a little problem understanding all of this... Maybe it is just me... I've used MSDN now more then ever... Perhaps it is a good thing, but MSDN can be confusing and lack good explanation sometimes...

EDIT 01: Speaking of MSDN, I read that those functions have been remade better so I should use the onees listen in MSDN... Maybe you should look into this? Better performance with better string/filename/erorrhandling code? I am no expert in these affairs just yet.


Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Fri Sep 01, 2006 12:47 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
FILE is a structure used to hold information about the file that you are either reading from or writing to. In the case above, what I do is create a file pointer (*fp) using the fopen function.

The sprintf() function is explained here: https://msdn.microsoft.com/library/defa ... printf.asp

The general idea with sprintf is to format a string (passed in as the first parameter) to something .... passed in as the next parameter(s). So for instance:

sprintf(szResult, "Hi There");
this makes szResult = "Hi There"

You can also pass in parameters/values into sprintf like this:

sprintf(szResult2, "My Number is: %d",iValue);
Here szResult2="My Number is: #" where # is what ever variable iValue holds.

If you want to pass a string into sprintf, then you use:
sprintf(szResult3,"My string [%s]",szString);

Now szResult3="My string [****]" where **** is what ever the variable szString holds.

EDIT: Microsoft made some changes to sprintf in the 2005 release of Visual Studio. That is why online, MSDN may say to use different functions. Since I'm using VC++ 2003 I do not talk about the new functions.


Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Fri Sep 01, 2006 4:48 pm 

Joined: Sun Feb 11, 2007 10:04 am
Posts: 16
OK cool. I wish you used 2005... Then you would have a very updated set of functions and stuff like that... Do you know where I can find a tutorial/sheet explaining the different things you can put inside strings. As you have done with the %d and other of those in-string-functions, or whatever you call them.

I am gonna watch the rest now, thank you for the reply, I am gonna fill this forum up with question, suggestions and more... Since you wanted it ;D I will post anything else about this video in a moment.


Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Fri Sep 01, 2006 5:06 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
Read this: https://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_format_specification_fields_.2d_.printf_and_wprintf_functions.asp

That shows you all the different formats that you can use. Generally you will use:

%d for integers
%s for strings
%f for floating point numbers

If someone wants to donate a full version of Visual C++ 2005 to me :wink: then I'd be happy to convert everything over, but right now I can't afford to buy a new compiler. So that is why I am sticking with VC++ 2003.

Please post as many questions as you can think of. The more you ask, the better I can make the VMK's. Also, it will help out anyone else that may be reading the forum.


Last edited by Marek on Tue Aug 19, 2008 5:23 am, edited 1 time in total.

Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Wed Aug 01, 2007 4:59 pm 

Joined: Wed Aug 01, 2007 4:26 pm
Posts: 2
Firstly I would like to say thank you very much for these tutorials, they are very well made and I appreciate the effort you have gone through. Secondly, I was wondering about the first four lines of the setError method of the ErrorHandler, I'm not sure the variable arguments bit is supposed to do? To me vsprintf(m_szErrorMessage, _szMessage, ap) looks like it is sending the next optional argument in the *format* of _szMessage to m_szErrorMessage, which (I think) in the long run does exactly the same as sprintf(m_szErrorMessage, _szMessage) if I am right?

If I am wrong please don't hesitate to tell me so!

Thanks again! - Ross


Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Wed Aug 01, 2007 7:01 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
You are correct, the vsprintf function does basically the same thing as sprintf however it is able to parse input into the SetError function in a much nicer way. For example, by using vsprintf, you are able to call the SetError function like so:

m_pErrorHandler->SetError(EC_Error, "I have %d parameters: P1=%1.3f, P2=%f, and P3=%5d", iNumParam, fParam1Value, fParam2Value, iParam3Value);


Notice that after the error code (EC_Error) I have a string followed by a comma and then a bunch of parameters. All of this stuff gets parsed correctly by vsprintf so that the result gets placed into the m_szErrorMessage. The function's definition says that we are expecting ErrorCode EC, const char *szMessage, ...

The three dots ... tell the compiler there could be any number of parameters passed into this function (or none after the const char*)

You could replace this function's definition with SetError(ErrorCode EC, const char *szMessage) but then all the parsing of your data would have to happen before you call SetError (You would then use sprintf, to parse your desired result, and pass this new string into the SetError function). By using vsprintf, the parsing happens after you call SetError.


Last edited by Marek on Tue Aug 19, 2008 5:26 am, edited 1 time in total.

Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Thu Aug 02, 2007 11:08 am 

Joined: Wed Aug 01, 2007 4:26 pm
Posts: 2
Ah that makes perfect sense now, thanks very much! :)


Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Tue Aug 07, 2007 5:25 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
You will notice that I like to use sprintf() a lot when copying strings from one variable into another. To be absolutely safe that you will not go beyond that memory that you are allowed to over write, it is advised that you instead use _snprintf()

for example, instead of:

char szOutput[12];
float dValue = 3.14;

//replace this
sprintf(szOutput,"Value: %1.2f",dValue);

//with this
_snprintf(szOutput,12,"Value: %1.2f",dValue);
szOutput[11] = 0;


This way if dValue is changed to have more digits you will not over write beyond the 12 characters that you are allowed to write into the szOutput variable.


Last edited by Marek on Tue Aug 19, 2008 5:30 am, edited 1 time in total.

Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Fri Aug 31, 2007 4:27 am 

Joined: Tue May 01, 2007 2:55 pm
Posts: 96
Location: Behind you
in this video you use _strdate en _strtime, are those two functions windows specific?

If s, can you simply use some other library to make them OS independant?


Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Fri Aug 31, 2007 6:02 am 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
I have never converted a Windows program to another OS so I don't know the function calls required to replace _strdate/_strtime. But don't worry, there will be an equivalent function replacement in the other OS. It is important to understand what the code does, so that when you do convert to another language/OS the process is not difficult.


Offline
 Profile  
 
 Post subject: Re: GameDev VMK 2 - Error Handler class
PostPosted: Sat Sep 01, 2007 4:17 am 

Joined: Tue May 01, 2007 2:55 pm
Posts: 96
Location: Behind you
Well, I am not converting it - but rather making my version cross-platform, which is a bit harder.

For _strdate/_strtime functions there must indeed be an answer, but the MessageBox you use in ShowErrorMessage(), is a bit harde. I am still thinking what I'll do with it, maybe I'll cut out the complete function (you do have the log after all).


Offline
 Profile  
 
 Post subject:
PostPosted: Sun Mar 09, 2008 7:27 am 

Joined: Tue Feb 26, 2008 3:30 am
Posts: 3
I've created my own error handler that works different from yours. Basically what I've done is to create a error handler class (CErrorHandler) with a static method called Print.

So whenever I want to handle an error I just write this:

if(!Initialize())
{
  CErrorHandler::Print("Error Initializing");
  return false;
}


This way, I don't need to send a pointer of the error handler to all classes that needs to handle error messages. I simply just call it's method directly in code.


Offline
 Profile  
 
 Post subject:
PostPosted: Fri Apr 18, 2008 5:54 am 

Joined: Tue May 01, 2007 2:55 pm
Posts: 96
Location: Behind you
The downside is that you can no longer store any data related to the error...

What you could also do is make the errorHandler global. That would have the benefits you are looking for, without the down-side.


Offline
 Profile  
 
 Post subject:
PostPosted: Tue Aug 19, 2008 12:22 am 

Joined: Wed Aug 06, 2008 7:53 pm
Posts: 182
Location: Russia
Quote:
The downside is that you can no longer store any data related to the error...

Not necessarily. Data related to the error could be static as well, namely be static class data-members :wink:

In general, there is so called “singletonâ€


Offline
 Profile  
 
 Post subject: one question and two proposals
PostPosted: Tue Aug 19, 2008 12:40 am 

Joined: Wed Aug 06, 2008 7:53 pm
Posts: 182
Location: Russia
Hi everybody and all.
Let me do some comments/questions upon this VMK002-ErrorHandler.

1). I wonder is there any reason to open/close the log file each time you need to write a string to it? A more standard way to deal with log-file is to open it in the ctor (constructor), keep the file handle, then close it in dtor. This is in particular why destructors has been invented for. So, whenever you need to put a message in log-file you just use the file handle, i.e. FILE * m_hFile, and you do not need to keep the whole file name as a member-data then. In such case you escape all additional overheads associated with open/close. The only rationale why to use open/close pair for every write operation is a reliability. Even in case of unexpected crash of the app last written message is going to become stuck in log-file. However, if you keep handle (as I’m proposing) you can reach the same effect via proper invocation of fflush(FILE * handle), which writes (flushes) internal file buffers to disk. Or I missed something?

2). One little proposal on log-file name checker. In ctor ErrorHandler::ErrorHandler() you have following code:
if ((strlen(filename)>4) && (filename[strlen(filename)-4] == ‘.’)) {
…
}


My proposal based on your code:
if ( (strlen(filename) > 2) && (strrchr(filename, '.')) ) {
…
}

A good news about the later is that you are not forced to use 3-letters’ file extension. It is allowed to use even the name like this: “x.yâ€


Offline
 Profile  
 
 Post subject: switch( ) statement internal mechanics
PostPosted: Sun Sep 14, 2008 1:23 am 

Joined: Wed Aug 06, 2008 7:53 pm
Posts: 182
Location: Russia
For completeness we also should mention another standard way which the compilers use to implement switch statement, notably – jump-table. The later is as fast as explicitly used array. However, in both these cases there are certain restrictions on indices, e.g. their values must be adjacent.


Offline
 Profile  
 
 Post subject:
PostPosted: Mon Jun 01, 2009 7:08 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
In Ghost Toast VMK17B you'll see that I updated the error handler class so that it can be accessed from anywhere using the get() function.


Offline
 Profile  
 
 Post subject: Re: one question and two proposals
PostPosted: Mon Jun 15, 2009 11:37 am 

Joined: Tue May 01, 2007 2:55 pm
Posts: 96
Location: Behind you
BugHunter wrote:
It's a joke to compare a performance of switch-statement versus array-access one, but theoretically speaking, "switch()" speed is O(N) – linear search in case of naive release, or O(log(N)) for advanced bin-search release (this stuff is about compiler quality).


I wanted to note that while what you say is true, it is not applicable here. The amount of elements in the array / switch is constant, thus you can't say it is O(N)/O(log(n))... *
Because n is constant, both array access and switch access are O(1), no matter what implementation is used. Array access is probably still faster, but that's because we know the constant factor for c array access is really low - it has nothing to with "if the n is not constant switch access is O(n)/O(log(n))".
So yes, your method is probably faster, but your speed analysis is worthless.



*Yes, technically you could. And you'd even be right. Just pretend these Os are thetas.


Offline
 Profile  
 
 Post subject: switch() vs array DEUX 8)
PostPosted: Mon Jun 15, 2009 11:53 pm 

Joined: Wed Aug 06, 2008 7:53 pm
Posts: 182
Location: Russia
Hi Jasper and all.

Jasper wrote:
your speed analysis is worthless

I fully agree with this statement since it was a joke ab origin (from the very beginning). My main point was to show that there is another amusing way to implement switch-alike logic.

In our certain case we can deduce exact values in CPU ticks, but when I wrote the previous opus I was speaking about general case and the question was: what is the complexity (in general) of switch-statement versus an access-by-index.

Jasper wrote:
Because n is constant, both array access and switch access are O(1)

From HLL (high level language) standpoint we could say so. But it is not the case when we come down to the real implementation in machine code.

Array access is just one instruction, such as mov edx, my_array[esi*4] Thus it is only a couple of CPU ticks, basically a constant time O(1).

switch()-statement:
in general you have no chance to wrap switch statement in a couple of opcodes except one special case, when (as I wrote above) the case-constants belong to relatively small range, i.e. ( TheBiggest – TheSmallest ) < 256.

A canonical implementation of the switch is (an unrolled) linear search. Giving it an estimate we can speak about the worst O(N) and average case O(N/2).

Again, if compiler is smart enough it can build a fixed bin-tree, replacing a linear search with bin-search, which complexity is O(log(N)). I.e. if we have 64 case-constants the code will do only 6 comparisons. In the next post I put a toy example, playing with which one can find some interesting facts about how the compiler implements switch-statement.
Namely, when I analyzed an output (release) assembler following traits were discovered (as expected).
1) if the range is small, the VC generates jump-table
2) if the range is small but there are some values that are far from that range, the compiler processes such “out-of-range” values separately, then uses jump-table for the rest. Example: consider values: { 3, 4, 5, …10, 11, 2222, 4444 }. Then for 3…11 it uses jump-table, but 2222 and 4444 are treated separately.
3) if the range is big, then compiler builds a static bin-tree. For instance for values { 1111, 2222, 3333, …, 9999 } it will make a bin-tree.

I could tell more but there is not enough place here. :)

Last statement. Beginning with the time when caching and pipelines were introduced into the hardware world we can only speak about the number of CPU clocks (ticks) per operation (i.e. array element access theoretically takes say 2 clocks), not about the exact time in some units (i.e. nanoseconds), since that time is highly depends on the presence of given data in the cache lines. The sad story is that on modern architectures an access to the non-cached item takes up to 200 CPU ticks (cache-miss penalty). Therefore, nowadays memory access optimization is much more profitable for performance gains than code polishing (algorithmic optimization is still in demand, obviously, and always will be). Unfortunately, there is no simple and direct way to optimize memory access. My favorite source of tricks in this area are undying (as far as they are being updated :) ) creations of Agner Fog: http://www.agner.org/optimize/ (again).

In line with this last affirmation my former proposal to replace the switch() with array-access is worthless indeed. You hit me. ;)


Offline
 Profile  
 
 Post subject: a toy example; play and see;
PostPosted: Mon Jun 15, 2009 11:56 pm 

Joined: Wed Aug 06, 2008 7:53 pm
Posts: 182
Location: Russia
A toy example:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include <iostream>


#ifdef _UNICODE
#define tcout std::wcout
#else
#define tcout std::cout
#endif

using std::endl;


void array_access( int i )
{
    static int a[] = { 1, 3, 5, 7, 11, 13, 17, 21, 23, 29, 31 };

    tcout << _T( "array_access( " ) << i << _T( " ) \t = " );

    if ( i < _countof( a ) )
        tcout << a[ i ] << endl;
    else
        tcout << _T( "out of range" ) << endl;
}


void switch_map( int i )
{
    tcout << _T( "switch_map( " ) << i << _T( " ) \t = " );

    // play with case-constants and see an release-asm output
    //
    switch ( i )
    {
        case  1: tcout << _T( "case #  1" ) << endl; break;
        case  3: tcout << _T( "case #  3" ) << endl; break;
        case  5: tcout << _T( "case #  5" ) << endl; break;
        case  7: tcout << _T( "case #  7" ) << endl; break;
        case 11: tcout << _T( "case # 11" ) << endl; break;
        case 13: tcout << _T( "case # 13" ) << endl; break;
        case 17: tcout << _T( "case # 17" ) << endl; break;
        case 21: tcout << _T( "case # 21" ) << endl; break;
        case 23: tcout << _T( "case # 23" ) << endl; break;
        case 29: tcout << _T( "case # 29" ) << endl; break;
        case 31: tcout << _T( "case # 31" ) << endl; break;
        default: tcout << _T( "default case" ) << endl;
    }
}


int _tmain(int argc, _TCHAR* argv[])
{
    ::srand( ::GetTickCount() );

    const int LIMIT = 0xA;
    const int COUNT = 0x4;

    tcout << ( sizeof( TCHAR ) == 1 ? _T( "ASCII mode" ) : _T( "UNICODE mode" ) ) << endl;

    tcout << endl;
    {
        for ( int i = 0; i < COUNT; ++i ) array_access( ::rand() % LIMIT );
    }
    tcout << endl;
    {
        for ( int i = 0; i < COUNT; ++i ) switch_map( ::rand() % LIMIT );
    }
    tcout << endl;

    return 0;
}


:roll:



_________________
«Computer scientists deal with algorithms that you may call practical in theory but unpractical in practice.» © Timothy Gowers
Offline
 Profile  
 
 Post subject: placement of SetError
PostPosted: Fri Sep 11, 2009 11:38 am 

Joined: Fri Aug 08, 2008 6:50 am
Posts: 9
Location: Norway
While I was converting this VMK to linux I got some strange files created every time my application was running. After tracking down this error I discovered that SetError() should be placed after the first "if-else", like this:
   //SetError(EC_NoError, "No Error"); //moved down

   //use default file name
   if (filename == NULL)
   {
      sprintf(m_szFilename, "errorLog.txt");
   }
   else
   {
      //determine if .txt extension is needed
      if ((strlen(filename)>4)&&(filename[strlen(filename)-4] == '.'))
      {
         sprintf(m_szFilename, "%s", filename);
      }
      else
      {
         sprintf(m_szFilename, "%s.txt", filename);
      }
   }
   
   SetError(EC_NoError, "No Error"); //and placed down here


Moving SetError() solves the problem and seems to work properly now.
This thingy might not be an issue in windows, but in linux it sure is.


Offline
 Profile  
 
 Post subject:
PostPosted: Fri Sep 11, 2009 12:36 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
Thanks for pointing this out MindProse. You are correct, there is a bug here. SetError should only be called after m_szFilename has been defined.


Offline
 Profile  
 
 Post subject:
PostPosted: Sun Apr 18, 2010 6:21 pm 

Joined: Sun Apr 18, 2010 11:46 am
Posts: 8
Ok, so my project is compiling fine, but the ErrorHandler.cpp and ErrorHandler.h won't stay in the ErrorHandler file in the directory. When I'm in visual c++ they appear to be in the correct files. When I look in the ErrorHandler file, there is an ErrorHandler.cpp and an ErrorHandler.h file, but I don't think they are the ones that are being compiled. If I try to move them into the file they should be, and write over the other files, when I'm in visual C++ and try to edit them, it says it cannot open the file.

I'm using Visual C++ 2008 Edition.

What is going on?


Offline
 Profile  
 
 Post subject:
PostPosted: Sun Apr 18, 2010 6:55 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
AdamD wrote:
Ok, so my project is compiling fine, but the ErrorHandler.cpp and ErrorHandler.h won't stay in the ErrorHandler file in the directory. When I'm in visual c++ they appear to be in the correct files. When I look in the ErrorHandler file, there is an ErrorHandler.cpp and an ErrorHandler.h file, but I don't think they are the ones that are being compiled. If I try to move them into the file they should be, and write over the other files, when I'm in visual C++ and try to edit them, it says it cannot open the file.

I'm using Visual C++ 2008 Edition.

What is going on?


I'm not quite sure what you mean. You can remove the files from your project, and then insert them back in by selecting the files that you want to use.

Alternatively, you can press Alt+Enter to get the property page for a selected file and look at the path that it is using. If the path is pointing to the wrong place, Visual Studio will not be able to open the file when you double click on it.

It is important to know that inside Visual Studio, if you drag your .h and .cpp files around and put them into folders, you are not actually moving the files around on your hard drive.


Offline
 Profile  
 
Display posts from previous:  Sort by  
 Page 1 of 2 [ 36 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Jump to:  

cron