I've been thinking about this bug for a while... And my guess is it's going to crop up again and again in other codeblocks unless a new "creation" system, erm... format? meh... anal retentivness... is used. I was thinking of going over every object, and making the constructor set values to NULL, 0, etc... Add in a "static <type>* GetInstance(void)", or "static void GetInstance(<type>&)" to all the objects. By doing this, at startup, any global objects can be "init" in winmain which forces a "creation priority". So the program starts up, runs through each global object's constructor (which set the memeber values to 0, NULL, etc...) then winmain is encountered. Each global object's "GetInstance" function is called. Inside the GetInstance, a singleton is implemented, or not, depending on the object. After that a call from GetInstance to the objects "init()" is made. Init will do things like calling other global objects, creating memory for strings, or BYTE streams, etc... This allows us (the coders) to say what object comes into existance first, and what comes into existance last. It also gives us a better opertunity to say what object is "deleted" first, and what is "deleted" last. Here's a sort of template of what that would entail...
Code: Select all
class CTemplate // of a regular object; ie: not a singleton
{
public:
static CTemplate GetInstance(/*Params for constructor*/
UINT uiValue, BYTE* pByteData)
{
// Create the object
CTemplate NewTemplate();
// Init the member variables, and do init work
NewTemplate.Init(/*Params for constructor*/uiValue, pByteData);
return NewTemplate;
}
/* public member functions, and variables go here */
private:
CTemplate(/*No params for the new constructors*/)
: m_uiValue (0),
m_pByte (NULL)
{}
void Init(/*Params for constructor*/ UINT uiValue, BYTE* pByteData)
{
m_uiValue = uiValue;
m_pByte = pByteData;
// Or get size of byte data, and create a
// copy using "new BYTE[]" or malloc
// Make calls to other (global?) objects all the way down here!
}
};
Could also look up some pragmas to "poison" or at least "warn" about using an objects creator, and only disable that poisoning durring that objects GetInstance; if we wanted public constructors, that is. I know it's alot of code to change, and it's alot of force for such a small problem, but this could make the game that much more stable. First off, because the startup is cleaner. Secondly, because all the objects being created durring the game are forced into cleanliness (ie: bad memory allocation, deallocation will be easier to find). Thirdly, (if I remeber correctly; because of larger offsets to the function tables) alot of code in an objects constructor has a tendancy to slow down the thread (sure, by a few 'ticks', but still... we're being anal, remeber?). We could even add in something like this to each public member function:
Code: Select all
#ifdef DEBUG
if (! memeber_debug_bConstructorRun)
MessageBox(NULL, "Trying to use CTemplate::DoSomething() but object CTemplate does not exists", "Object Usage Error", MB_OK | MB_ICONERROR);
if (! memeber_debug_bInitRun)
MessageBox(NULL, "Trying to use CTemplate::DoSomething() but object CTemplate was not init", "Object Usage Error", MB_OK | MB_ICONERROR);
#endif
Hope one of you lead devs can get back to me soon :D