Click here to Skip to main content
15,848,451 members
Please Sign up or sign in to vote.
3.50/5 (2 votes)
See more:
Hello All,

I am having a memory leak in my application. When I use semaphore, the threads that are stuck waiting for other threads to arrive are giving me memory leak.

How do I release threads that are stuck and how do I know how many are in there?

Any help will be appreciated.

Thanks In advance.

C++
void CTestManualThreadDlg::OnStartStop()
{
	m_EventEnd.ResetEvent();
	m_pMainThread = AfxBeginThread(MainThread, this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
	m_pMainThread->m_bAutoDelete = FALSE;
	m_pMainThread->ResumeThread();
}
UINT CTestManualThreadDlg::MainThread(LPVOID p)
{

	CTestManualThreadDlg * Me = (CTestManualThreadDlg *)p;
	Me->MainThread();
	return 0;
}
void CTestManualThreadDlg::MainThread()
{
	static int m_mainvar = 0;
	CString Test;
	while(WAIT_TIMEOUT == ::WaitForSingleObject(m_EventEnd.m_hObject, 0))
	{
		m_mainvar++;
		Test.Format("%d", m_mainvar);
		m_MainThread.SetWindowText(Test);
		for (int x= 0; x<10; x++)
		{
			ChildThreadData *pData = new ChildThreadData;
			pData->pDlg = this;
			pData->ThreadNumber = x;
////THIS ARE SET FOR AUTODELETE....
			m_pChildrenThread[x] = AfxBeginThread(ChildThread, pData,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
			m_pChildrenThread[x]->ResumeThread();
		}
	}
	m_EventEnd.SetEvent();
}

UINT CTestManualThreadDlg::ChildThread(LPVOID p)
{
	ChildThreadData *pData = (ChildThreadData *)p;
	pData->pDlg->ChildThread(pData->ThreadNumber);
	delete pData;
	return 0;
}
void CTestManualThreadDlg::ChildThread(int ThreadNumber)
{
	CString Test;
	m_pMainThread->SuspendThread();
	m_ChildSemaphore.Lock();
	g_childvar1++;
	Test.Format("%d", g_childvar1);
	m_ChildThread1.SetWindowText(Test);
	g_childvar++;
	Test.Format("%d", g_childvar);
	m_ChildThread2.SetWindowText(Test);
	m_ChildSemaphore.Unlock();
	m_pMainThread->ResumeThread();
}
void CTestManualThreadDlg::OnExit()
{
	
	m_EventEnd.SetEvent();
	::WaitForSingleObject(m_EventEnd.m_hObject, INFINITE);
	m_pMainThread->Delete();
	OnOK();
}
Posted
Updated 24-Jul-12 13:10pm
v2
Comments
Sergey Alexandrovich Kryukov 24-Jul-12 16:51pm    
What makes you thinking that this is the real reason for your memory leak?
--SA
FISH786 24-Jul-12 16:55pm    
If I let the threads run without Semaphore and I pause the creation of the threads before I exit, I don't get memory leak, however my threads are not in sync. As soon as I use semaphore my threads are in sync but when I exit I get memory leak.
Sergey Alexandrovich Kryukov 24-Jul-12 16:53pm    
And how do you create threads? (And what's your platform?) Windows thread API can create memory leaks; you need to use _beginthread, _beginthreadex.
--SA
FISH786 24-Jul-12 16:57pm    
I am using AfxBeginThreads. I have been using it for a while. Not having any problems so far.
pasztorpisti 24-Jul-12 17:36pm    
AfxBeginThreads() is an MFC API and the leak is probably some kind of resource MFC allocates for the management of threads, but the real problem is not the leak as SA pointed out. You can use any API, most of them are not having leaks (except old versions of CRT beginthread/endthread and some pthread libraries have known leak bugs - small and fixed in size on global storage so its not really harmful).

1 solution

This is a wrong approach. If you have threads stuck because they are waiting for each other forever, this is a problem called deadlock. It can be much more serious than your memory leaks. You should not aim to "release" them; you should prevent them. Please see:
http://en.wikipedia.org/wiki/Deadlock[^].

You can achieve this goal through accurate architecture and design of your system. One interesting and simple method of threaded system analysis is using the Petri net formalism. Please see:
http://en.wikipedia.org/wiki/Petri_net[^].

This excellent Microsoft article teaches us how to use it in practice:
http://msdn.microsoft.com/en-us/library/ms810303.aspx[^].

Now, let's come back to memory leaks. Nothing in your question tells me that you have detected the real reasons for your memory leaks. You should approach this problem from accurate diagnostics. You can use some development tool from the class of tools called "memory debugger". Please check the list of available memory debuggers found in this article:
http://en.wikipedia.org/wiki/Memory_debugger[^].

Good luck,
—SA
 
Share this answer
 
Comments
FISH786 24-Jul-12 17:04pm    
Thank you. I will read on the articles.
pasztorpisti 24-Jul-12 17:49pm    
+5 especially for the petri net part I didn't know and can come quite handy to teach stuff and to design.
One more thing I would add as an advice to the asker is to wrap the low level threading API (threads, synchronization primitives - criticalsection, event) into classes. This way you can replace the underlying api easily (easy porting to crossplatform), you can intorduce some printf() style oldschool debugging inside the methods of your classes, collecting statistics in the classes (how many threads are waiting for a lock, what is the spincount of a spinlock, etc...) that can also be used to debug and optimize your code. One thing I usually do is putting an assert to the destructor of my thread objects so that they fire if the destructor tries to execute before the encapsulated thread terminated. This usually helps me to catch a lot of bugs.
Sergey Alexandrovich Kryukov 24-Jul-12 18:11pm    
Thank you for voting and -- absolutely great point about the wrappers; they can help same many problems at once. For example, I've published my thread wrapper code for .NET in couple of the answers; where it is even more powerful, because it also helps to avoid that pointless parametrized thread start method which requires type casting; and this is because the thread method can be an instance method, so the reference to the wrapper will be passed via "this" parameter; too bad this is not allowed in C++ threads, so just one problem would be passing a pointer to the wrapper to the thread.
--SA
pasztorpisti 24-Jul-12 18:21pm    
Its completely possible in C++ as well! Every threading api I know allows passing in a (void*) parameter to its createthread() function! My threading classes ususally have a pure virtual Run() method (instance method). The thread interface I need is Start(), Wait(). There is another virtual method: OnFinished() that is executed after the thread object has changed to finished state - that is, the thread has finished executing the Run() method. I call the OnFinished() method in a fashion that it is valid to delete the thread object from there.
Sergey Alexandrovich Kryukov 24-Jul-12 18:24pm    
I know, and this is how I did it. Again, wrapping the thread in a class is a very good idea.
--SA

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