Click here to Skip to main content
13,005,198 members (62,689 online)
Rate this:
Please Sign up or sign in to vote.
See more:

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:
clase CThreadPoolBase
    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
    void   OnThreadFinished(LPVOID thr)
      <pre lang="cs">CThread *pthr = static_cast<CThread*>(thr);
    if( pthr != NULL )
        MoveToIdleList(pthr); //move itself to idle list
        cout<<"\t***[ERR_OnThreadFinished], Received error thread notify."<<endl;
    int noff = GetIdleNum()-GetInitNum();
    if (noff>0) //if too many idle threads, kill some



3. Thread: class of thread handling:
#include  "CThreadPoolBase.h
class Thread:
    Thread(CThreadPoolBase *pool=NULL):m_pool(pool){}
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;
    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 16:49pm
Updated 14-Mar-11 18:30pm
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?
Laxmikant_Yadav 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).
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().
Rate this: bad
Please Sign up or sign in to vote.

Solution 2

What do you see when you step through your code in the debugger?
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 Lindquist 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 Lindquist 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
Please Sign up or sign in to vote.

Solution 3

This call is a direct call to the thread manager (non-thread safe!):

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.
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()

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<initnum;i++)
Thread *thr = new Thread(this); //so,Thread::m_pool was pointed to concrete POOL

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.
Albert Holguin 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 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:


catch (...)
std::cout<<"\t*** [ERR] *** :: Error happened CWorkThread::OnTask(LPVOID lpvData)"<<std::endl;
Espen Harlinn 17-Mar-11 10:52am
Good effort - a 5 :)
Rate this: bad
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 */);       
        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");

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.
Rate this: bad
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.
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)

  Print Answers RSS
Top Experts
Last 24hrsThis month

Advertise | Privacy | Mobile
Web01 | 2.8.170627.1 | Last Updated 15 Mar 2011
Copyright © CodeProject, 1999-2017
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