Click here to Skip to main content
15,881,898 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,all:

When I was trying to design a thread pool, after thread job done, I need to notify the pool to do some work,like moving this thread from busy list to idle list,I designed 3 classes in 3 .h files:
1. CThreadPoolBase,an interface for an ending thread to notify the concrete thread pool to do some work:
/*CThreadPoolBase.h*/
clase CThreadPoolBase
{
public:
    virtual ~CThreadPoolBase()=0{}
    virtual void OnThreadFinished(LPVOID thr)=0; //para thr was used to pass a Thread*
}



2. CThreadPool: the concrete thread pool that fix the job:
/*CThreadPool.h  */
#include  "CThreadPoolBase.h"
class CThreadPool:public CThreadPoolBase
{
public:
    ...
    void   OnThreadFinished(LPVOID thr)
    {
      <pre lang="cs">CThread *pthr = static_cast<CThread*>(thr);
    if( pthr != NULL )
        MoveToIdleList(pthr); //move itself to idle list
    else
    {
        cout<<"\t***[ERR_OnThreadFinished], Received error thread notify."<<endl;
        return;
    }
    int noff = GetIdleNum()-GetInitNum();
    if (noff>0) //if too many idle threads, kill some
    {
        DeleteIdleThread(noff);
    }   


}

}

3. Thread: class of thread handling:
#include  "CThreadPoolBase.h
class Thread:
{
public:
    Thread(CThreadPoolBase *pool=NULL):m_pool(pool){}
    ~Thread(){}
    ... 

BOOL Thread::OnTask()     
{
    ...// do some work here
    
    //notify the pool that 'this' thread has finished its work
    m_pool->OnThreadFinished(this);	//Exception caught <big>sometimes</big>
    return TRUE;
}
private:
    CThreadPoolBase *m_pool;
}

I got this exception:
Unhandled exception in .exe 0xC0000005 access violation

25: m_pool->OnThreadFinished(this);
0040205C mov esi,esp
0040205E mov ecx,dword ptr [ebp-4]
00402061 push ecx
00402062 mov edx,dword ptr [ebp-4]
00402065 mov ecx,dword ptr [edx+50h]
00402068 mov eax,dword ptr [ebp-4]
0040206B mov edx,dword ptr [eax+50h]
0040206E mov eax,dword ptr [edx] //it stopped here
00402070 call dword ptr [eax+4]
00402073 cmp esi,esp
00402075 call __chkesp (0040ed50)


Anybody would kindly tell me, what's the problem, and how did it happen?
Thank you !
Posted
Updated 14-Mar-11 18:30pm
v6
Comments
Stephen Hewitt 10-Mar-11 0:39am    
The first thing to do is attempt to reproduce the problem in a debug build. Actually, this looks like a debug build looking at the machine code. Why isn't there any source?
LaxmikantYadav 10-Mar-11 2:07am    
Error 0xC0000005 means the program has attempted to access memory that it shouldn't. You need to read the error log, or post it here.
mbue 10-Mar-11 6:05am    
It seems your class is destroyed while the thread is running. If you're using COM, you should AddRef on the beginning of your thread and Release at the end. Otherwise you should enshure your class cannot been deleted while thread is running. You can do that in your destructor you mut wait until the thread execution is finished by WaitForSingleObject(hYourThread,INFINITE).
Regards.
Rajesh Katalkar 15-Mar-11 1:20am    
where are you allocating memory for m_pool member in your cthread class.
scu_sundy 15-Mar-11 1:30am    
I dont need allocate memory in class 'Thread',m_pool was passed and set to "CThreadPool*" after Thread object was created in CThreadPool::CThreadPool().

What do you see when you step through your code in the debugger?
 
Share this answer
 
Comments
scu_sundy 10-Mar-11 0:40am    
stop here:
25: m_pool->OnThreadFinished(this);
and got this:
Unhandled exception in .exe 0xC0000005 access violation
Niklas L 10-Mar-11 7:32am    
Inspect your variables. It's either m_pool, this or *this that contains improper values. Verify that their respective members are looking ok. When you know this, you have better chances of finding the offending code.
scu_sundy 15-Mar-11 1:59am    
I've found that it was the m_pool got a 'NULL' value caused the problem, but why ? I passed and set m_pool when Thread was created. And problems wont happen at first,which is meaned that some of 'Thread::m_pool != NULL', how did it happend?
Niklas L 15-Mar-11 5:17am    
In your Thread class, make some pre- and post-condition checks in your functions. E.g add ASSERT(m_pool != NULL); first and last in every function. If someone is setting m_pool to NULL somewhere, you will catch him quickly.
This call is a direct call to the thread manager (non-thread safe!):
m_pool->OnThreadFinished(this);


Its bound to cause problems because you actually DeleteIdleThread() within it (you try to delete the thread that called the method). The proper way of doing this within MFC would be to PostMessage() when you're done and wait for a synchronization signal. If you're not using MFC, just look up non-blocking thread calls and/or synchronization methods for whatever your framework happens to be.
 
Share this answer
 
v2
Comments
scu_sundy 15-Mar-11 0:00am    
Thank you Albert.
Fisrt of all, I ditn't use MFC;
second,I had tryed to debug and find the problem by change the Interface funtion OnThreadFinished()like this:
/*CThreadPoolBase.h*/clase CThreadPoolBase{public: virtual ~CThreadPoolBase()=0{} virtual void OnThreadFinished(/*LPVOID thr*/)=0; //NO Para passed }

And in CThreadPool::OnThreadFinished((/*LPVOID thr*/)
{/*it doing nothing*/}

In Thread::Ontask()
{
m_pool->OnThreadFinished(/*this*/);
}

After change, Problems still found!
Albert Holguin 15-Mar-11 0:11am    
did you make sure that m_pool was what you expect it to be?
scu_sundy 15-Mar-11 0:42am    
Yes,I'm sure that in the pool when thread was created, the CThreadPool* was passed to Thread::Thread(CThreadPoolBase* pool),code like below:

CThreadPool::CThreadPool(const int initnum)
{ for (int i=0;i
Albert Holguin 15-Mar-11 0:46am    
Where's the section of code where you generate the CThread (or Thread) object?
scu_sundy 15-Mar-11 1:15am    
In class CThreadPool's constructor, I create an initial list of thread,I passed this(that is CThreadPool*) to each thread:

Thread* thr = new Thread(this);AppendToIdleList(thr);

so that Thread::m_pool was pointed to the right concrete POOL.
I have found the problem,It's my fault,error was found in function CreateIdleThreadused to create idle threads dynamicly when necessary:

void CThreadPool::CreateIdleThread(const int num)
{
C#
for (int i=0;i<num;i++)
    {
        Thread *thr = new Thread(/*here I forgot to pass pointer this */);       

        AppendToIdleList(thr);
        m_VarMutex.Lock();
        m_nAvailNum++;
        m_VarMutex.Unlock();
        printf("\t\tCreate %d Idle thread . All=%d, busy=%d,Idle=%d\n",num,m_ThreadList.size(),m_BusyList.size(),m_IdleList.size());

        printf("*** Thanks a lot and best regards to all of you !! ^|^ ***\n");
   }


}
 
Share this answer
 
v3
Comments
Albert Holguin 15-Mar-11 9:46am    
Good! :) ...don't forget what I said in regards to m_pool->OnThreadFinished(this) being non-thread safe.... even if it works every time on your computer, that doesn't mean it'll work every time in every computer.
scu_sundy 15-Mar-11 10:42am    
I see.I should create a mutex for CThreadPool::OnThreadFinished(Thread*).
Thank you very much Albert.
This problem have to resolved by some changes in settings as given below
project properties --> general --> Project Defaults-->Use of MFC
To set the properties "Use MFC In A Shared DLL".

This will solve your problem.
 
Share this answer
 
Comments
scu_sundy 9-Mar-11 23:34pm    
thank you!
Problem still found after this setting.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900