Good afternoon. For a day and a half I've been trying to figure out the reasons for the memory leak messages (Memory Leaks Detected ...) in the OutPut of the project. And during these one and a half days, I managed to find out that the leaks are related to the flow and the transfer of parameters to it.

The program looks like this: Dialog box -> On it is placed CTabCtrl -> A window that is activated when a certain tab is open.

The structure and variables are declared in NewTabDlg.h:

HANDLE hListScan; CWinThread* cwListScan; CListCtrl ItemList; CButton ScanEnabled; typedef struct SData{ CButton* Button; CListCtrl* List; }SDataTrans; 

In NewTabDlg.cpp, when the CheckBox value changes, a stream is created:

 void NewDialog::OnBnClickedCheckscan(){ SDataTrans *data = new SDataTrans; data->Button = &ScanEnabled; data->List = &ItemList; if (ScanEnabled.GetCheck() > 0){ cwListScan = AfxBeginThread(&ListScanThread, (LPVOID)data, NULL, NULL, NULL, NULL); if(cwListScan->m_hThread) hListScan = cwListScan->m_hThread; } } 

And the stream function itself:

 UINT ListScanThread(LPVOID pParam) { SDataTrans * data = (SDataTrans *)pParam; while (data->Button->GetCheck() > 0) { CString strBuffer; for (int i(0); i <= MAX_ITEMS; i++) { if (lstrcmp(data->List->GetItemText(i, 0), SProd[i].Name) != 0) data->List->SetItemText(i, 0, SProd[i].Name); strBuffer.Format(_T("%i"), SProd[i].iPrice); if (lstrcmp(data->List->GetItemText(i, 1), strBuffer) != 0) data->List->SetItemText(i, 1, strBuffer); strBuffer.Format(_T("%i"), SProd[i].iAmount); if (lstrcmp(data->List->GetItemText(i, 2), strBuffer) != 0) data->List->SetItemText(i, 2, strBuffer); } Sleep(300); }; data->List->DeleteAllItems(); delete data; return 0; } 

Actually, the options for the development of events.

  1. While the program is running, if you don’t touch CheckBox at all, the stream does not start and, accordingly, there are no leaks when closing the application.
  2. If you start a stream by activating CheckBox and close the program without unchecking the CheckBox, a message appears about the memory leak "{1025} client block at 0x01AE6328, subtype c0, 68 bytes long.", "AtlTraceGeneral - a CWinThread object at $ 01AE6328, 68 bytes long. " But, if in OnClose () of the parent window to register: NewTabDlg.ScanEnabled.SetCheck (0); WaitForSingleObject (NewTabDlg.hListScan, INFINITE); OnDestroy (); That thread, judging by the load does not work (ie, does nothing), but the program also hangs and is waiting and does not end.

  3. While the program is running, we play with CheckBox, turn it on / off and successfully finish thread by stream. Remove the checkmark from the checkbox and close the program. -> We get a bunch of messages about a memory leak, and the more times they turned on / off, the more these messages.

Actually, I can’t even imagine because of what is happening. Already tried a lot of things.

  • In general, we managed to find out under what specific circumstances a leak occurs, but how to solve it ... A leak occurs when a parameter is passed to the stream, in this case, a structure. All because of her. Although it is removed at the end of the stream, a leak appears. - MecheniyChannel

2 answers 2

So where in your code is the CWinThread object CWinThread to by cwListScan cwListScan ? This object is created dynamically inside AfxBeginThread

 CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority, UINT nStackSize, DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES lpSecurityAttrs) { ... CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam); ... return pThread; } 

It is usually released inside an AfxEndThread called at the end of the thread.

 void AFXAPI AfxEndThread(UINT nExitCode, BOOL bDelete /* = TRUE */) { AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState(); CWinThread* pThread = pState->m_pCurrentWinThread; ... if (bDelete) pThread->Delete(); ... } 

At you call AfxEndThread not visible anywhere.

If you do not want to call AfxEndThread , then doing delete cwListScan is your responsibility.

The code, of course, is terrible in other respects, but nevertheless there is a considerable likelihood that your memory leaks - including this one.

  • That's right, I missed this line of code, I had to insert it right away. But in this case, leakage problems do not solve it. Leaks, which are described in the 3rd paragraph, still remain. Another interesting point is that when you close the program while the thread is still active, it doesn’t want to end on its own. And in such cases, even if it is registered with AfxEndThread, a leak from 2 points returns to me. - MecheniyChannel

Problem solved. This thread is a vivid example of human inattention, namely mine.

In the function from which the stream opened, the structure was not deleted. In general, correctly it looks like this:

 void NewDialog::OnBnClickedCheckscan(){ SDataTrans *data = new SDataTrans; data->Button = &ScanEnabled; data->List = &ItemList; if (ScanEnabled.GetCheck() > 0){ cwListScan = AfxBeginThread(&ListScanThread, (LPVOID)data, NULL, NULL, NULL, NULL); if(cwListScan->m_hThread) hListScan = cwListScan->m_hThread; } else { delete data; } // удаляем data } 
  • Strange decision. And why do you then first create this structure, and only then check whether it is needed? Why not scan ScanEnabled.GetCheck() > 0 first , and only then do new SDataTrans . And what you have done now looks like an attempt to suppress a bug with an anti-bug. - AnT