Hi all
I've got a problem with the use of two classes I made.
I made a thread class similar to the 'Thread' class in Java.
I have a class for handling the thread (called CMMThread)
and another one (called CMMThreadObject) as an interface
(like the 'Runnable' interface in Java).
I put both classes in a dll and try to use them from
a normal .exe .
When I derive a class from CMMThread everything works as
expected, but when I derive a class from CMMThreadObject,
create a CMMThread object with the object derived from
CMMThreadObject passed in the constructor, I get an
assertion failure when trying to destroy the object
derived from CMMThreadObject, I get the assertion
failure
Here's the code of my classes (only relevant part):
<code>
CMMThreadObject::~CMMThreadObject()
{
if ( thread )
{
delete thread; // --> call destructor of CMMThread
thread = 0;
}
}
CMMThread::CMMThread(CMMThreadObject * object)
{
this->object = object;
id = 0;
handle = 0;
running = 0;
exitcode = 0;
}
CMMThread::~CMMThread()
{
if ( object )
{
object->thread = 0;
object = 0;
}
if ( handle )
{
int sts = CloseHandle(handle);
handle = 0;
}
} // <-- error occurs when returning from here
void
CMMThread::Start(void)
{
if ( object )
{
object->thread = this;
handle = CreateThread(0,0,CMMThreadRunObject,object,0,&id);
// handle = _beginthread(CMMThreadRunObject,0,object);
}
else
{
handle = CreateThread(0,0,CMMThreadRunThread,this,0,&id);
// handle = _beginthread(CMMThreadRunThread,0,this);
}
}
// BounceProc to start the thread with an associated object
MMTHREADRESULT __stdcall
CMMThreadRunObject(void * arg)
{
CMMThreadObject * object = (CMMThreadObject *)arg;
MMTHREADRESULT result;
object->thread->running = 1;
result = object->Run();
object->thread->running = 0;
// _endthread();
ExitThread(result);
return result;
}
// BounceProc to start the thread (using a class derived from CMMThread)
MMTHREADRESULT __stdcall
CMMThreadRunThread(void * arg)
{
CMMThread * thread = (CMMThread *)arg;
MMTHREADRESULT result;
thread->running = 1;
result = thread->Run();
thread->running = 0;
// _endthread();
ExitThread(result);
return result;
}
</code>
And here's the code of my app using my classes:
<code>
class TestObject : public CMMThreadObject
{
public :
MMTHREADRESULT Run(void);
};
class TestThread : public CMMThread
{
public :
MMTHREADRESULT Run(void);
};
...
TestObject * object[5];
CMMThread * thread[5];
// Here I create 5 threads
for ( i = 0; i < c; i++ )
{
sprintf(threadname,"Thread #%d",i);
object[i] = new TestObject();
thread[i] = new CMMThread(object[i]);
thread[i]->Start();
printf("thread %d started\n",i);
}
// Here I wait for the threads to complete
for ( i = 0; i < c; i++ )
{
object[i]->Thread()->Wait();
}
// Here I try to destroy all objects
for ( i = 0; i < c; i++ )
{
delete object[i]; // <-- Failure occurs here (indirectly)
// 1st, the destructor of CMMThreadObject is called
// which then destroys the thread object (see above)
}
</code>
When returning from the destructor of CMMThread, I see the
following assembler code (from where the error occurs):
10001265 mov eax,dword ptr [ebp+8]
10001268 and eax,1
1000126B test eax,eax
1000126D je CMMThread::`scalar deleting destructor'+3Bh
(1000127b)
1000126F mov ecx,dword ptr [ebp-4]
10001272 push ecx
10001273 call operator delete (100022d6)
10001278 add esp,4
Inside the call of the 'operator delete', '_free_dbg' is called,
which then calls '_free_dbg_lk' from dbgheap.c which then fails
in the statement '_ASSERTE(_CrtIsValidHeapPointer(pUserData));'
I can't see a reason for that. Both objects are created by my
test application and I also try to destroy them from there.
I tried many other combinations, like destroying the thread
object inside a 'Destroy' method (delete this) or destroying
the two objects inside the the test application (delete object[i]
and delete thread[i]) but nothing helped.
I also tried to use the _beginthread and _endthread functions
from C++ (according to MSDN, this is the way to go for C++ programs).
Can someone please help me to find a solution (maybe need to
create my own 'operator new' and 'operator delete' methods?).
Alexander Kienzle