Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++
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 9-Mar-11 17:49pm
Edited 14-Mar-11 19:30pm
v6
Comments
Stephen Hewitt at 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?
Laxmikant_Yadav at 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 at 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 at 15-Mar-11 1:20am
   
where are you allocating memory for m_pool member in your cthread class.
scu_sundy at 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().
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

What do you see when you step through your code in the debugger?
  Permalink  
Comments
scu_sundy at 10-Mar-11 0:40am
   
stop here:
25: m_pool->OnThreadFinished(this);
and got this:
Unhandled exception in .exe 0xC0000005 access violation
Niklas Lindquist at 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 at 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 Lindquist at 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.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

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.
  Permalink  
v2
Comments
scu_sundy at 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 at 15-Mar-11 0:11am
   
did you make sure that m_pool was what you expect it to be?
scu_sundy at 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 at 15-Mar-11 0:46am
   
Where's the section of code where you generate the CThread (or Thread) object?
scu_sundy at 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.
Albert Holguin at 15-Mar-11 1:33am
   
that seems fine, make sure that the value in "this" matches the pointer m_pool right when you make that call to OnThreadFinished(), hopefully you have a debugger that'll allow you to break and see the values.
scu_sundy at 15-Mar-11 1:48am
   
My god,I debuged the program,when exception was caught and debug stopped,m_pool = 0x00000000.How could it be ? I've already passed the right CThreadPool* to class 'Thread''s constructor, I'm absolutely confused:
 
try
{
m_pool->OnThreadFinished();

}
catch (...)
{
std::cout<<"\t*** [ERR] *** :: Error happened CWorkThread::OnTask(LPVOID lpvData)"<<std::endl;
}
Espen Harlinn at 17-Mar-11 10:52am
   
Good effort - a 5 :)
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

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)
{
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");
   }
 
}
  Permalink  
v3
Comments
Albert Holguin at 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 at 15-Mar-11 10:42am
   
I see.I should create a mutex for CThreadPool::OnThreadFinished(Thread*).
Thank you very much Albert.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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.
  Permalink  
Comments
scu_sundy at 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)

  Print Answers RSS
0 OriginalGriff 365
1 Sergey Alexandrovich Kryukov 334
2 CPallini 275
3 DamithSL 230
4 Maciej Los 215
0 OriginalGriff 5,455
1 DamithSL 4,457
2 Maciej Los 3,885
3 Kornfeld Eliyahu Peter 3,480
4 Sergey Alexandrovich Kryukov 3,115


Advertise | Privacy | Mobile
Web02 | 2.8.141216.1 | Last Updated 15 Mar 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100