День добрый. Уже полтора дня пытаюсь разобраться в причинах сообщений об утечках памяти(Memory Leaks Detected...) в OutPut'е проекта. И за эти полтора дня мне удалось выяснить, что утечки связаны с потоком и передачей ему параметров.
Программа выглядит примерно так: Диалоговое окно -> На нём размещён CTabCtrl -> Окно, которое активируется, когда открыта определённая вкладка.
В NewTabDlg.h объявлена структура и переменные:
HANDLE hListScan;
CWinThread* cwListScan;
CListCtrl ItemList;
CButton ScanEnabled;
typedef struct SData{
CButton* Button;
CListCtrl* List;
}SDataTrans;
В NewTabDlg.cpp, при изменении значения CheckBox'а создаётся поток:
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;
}
}
И сама функция потока:
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;
}
Собственно, варианты развития событий.
Если запустить поток, активировав CheckBox и закрыть программу не сняв галочку с CheckBox'а, появляются сообщения об утечке памяти "{1025} client block at 0x01AE6328, subtype c0, 68 bytes long.", "atlTraceGeneral - a CWinThread object at $01AE6328, 68 bytes long". Но, если в OnClose() родительского окна прописать: NewTabDlg.ScanEnabled.SetCheck(0); WaitForSingleObject(NewTabDlg.hListScan, INFINITE); OnDestroy(); То поток, судя по нагрузке не работает(т.е. ничего не делает), но и программа зависает и находится в ожидании и не завершается.
Во время работы программы, играемся с CheckBox'ом, включаем/выключаем и поток за потоком успешно завершают. Убираем галочку с CheckBox'а и закрываем программу. -> Получаем кучу сообщений об утечке памяти, и чем больше раз включали/выключали, тем больше этих сообщений.
Собственно, даже предположить не могу из-за чего это происходит. Уже много чего перепробовал.
Так а где у вас в коде уничтожается объект CWinThread
, указуемый cwListScan
? Этот объект создается динамически внутри 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;
}
Он обычно освобождается внутри AfxEndThread
, вызываемого в конце потока
void AFXAPI AfxEndThread(UINT nExitCode, BOOL bDelete /* = TRUE */)
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
CWinThread* pThread = pState->m_pCurrentWinThread;
...
if (bDelete)
pThread->Delete();
...
}
У вас же вызова AfxEndThread
нигде не видно.
Если вы не хотите вызвать AfxEndThread
, то делать delete cwListScan
- это ваша обязанность.
Код, конечно, ужасен и в других отношениях, но тем не менее есть немалая вероятность, что ваши memory leaks - это в том числе именно оно.
Проблема решена. Данный тред - яркий пример человеческой невнимательности, а именно - моей.
В функции, из которой открывался поток, не удалялась структура. В общем, правильно это выглядит так:
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
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Есть у кого пример lstm сети? На гитхабе не нашел того, что подходит
Продолжение этой темы Ошибки в коде при решении уравнения переноса