Hi all,
I have a very puzzling problem that has been hard to find any help with on Google or on the archives here. I have a particular object which can be deleted correctly in one destructor -- but if instead that deletion occurs in a different destructor, I get a debug assertion failure.
I'll post some code and try to explain. A
HumanGameView is new'd in another part of the program, and then
HumanGameView::init() is called.
init() creates two objects: a
KeyboardInterpreter and a
ProcessManager. My class
KeyboardInterpreter derives from class
Process, and so it gets loaded into the
ProcessManager, which will eventually be responsible for updating it every game cycle.
The
ProcessManager, in its dtor, goes through all the processes it has been handed (the
KeyboardInterpreter is the only one so far) and deletes them. This is where the problem lies! When the
ProcessManager dtor tries to delete the
KeyboardInterpreter, I get a debug assertion failure in dbgdel.cpp, with the following expression: "_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)".
If, relenting, I never add the
KeyboardInterpreter to the
ProcessManager's list, and just delete it myself in
HumanGameView, it works fine -- but this breaks my design.
I hope someone with more expertise than me can tell me what's going on!
HumanGameView::HumanGameView() : Process(), mProcessManager(0), mKeyboardInterpreter(0)
{
// This line isn't involved in the problem.
HR(D3DXCreateSprite(gDevice, &mSprite));
}
HumanGameView::~HumanGameView()
{
// This line isn't involved in the problem.
RELEASECOM(mSprite);
if (mProcessManager)
{
delete mProcessManager;
mProcessManager = 0;
}
// If instead of being given to the ProcessManager, whose dtor
// deletes it, the KeyboardInterpreter is deleted here, there's no
// problem.
if (mKeyboardInterpreter)
{
delete mKeyboardInterpreter;
mKeyboardInterpreter = 0;
}
}
bool HumanGameView::init()
{
mKeyboardInterpreter = new KeyboardInterpreter();
if (!mKeyboardInterpreter->init())
return false;
mProcessManager = new ProcessManager();
// Commenting this next line fixes the problem, because the
// ProcessManager dtor never tries to delete mKeyboardInterpreter.
mProcessManager->addProcess(mKeyboardInterpreter);
return true;
}
ProcessManager::~ProcessManager()
{
// Delete all the processes in our list. The ProcessManager is
// responsible for handling pointer deletion, not the Process creator.
std::list<Process*>::iterator it;
for (it = mProcessList.begin(); it != mProcessList.end(); ++it)
{
Process* prcs = *it;
if (prcs)
{
// This delete line, when prcs is the KeyboardInterpreter,
// causes the debug assertion failure.
delete prcs;
prcs = 0;
}
}
}
void ProcessManager::addProcess(Process* process)
{
mProcessList.push_back(process);
}