MFC 工作线程在意外关闭时未清理
Posted
技术标签:
【中文标题】MFC 工作线程在意外关闭时未清理【英文标题】:MFC Worker Thread Not Cleaning Up On Unexpected Shutdown 【发布时间】:2016-02-29 09:52:19 【问题描述】:x64 ... VS2015... 在函数内部我这样调用线程:
CString* arr = new CString("test");
CWinThread *pThread;
if(!(pThread->AfxBeginThread(ThreadProc, (LPVOID)arr)))
delete arr;
对于过程:
UINT ThreadProc(LPVOID pParam)
CString* InputString = (CString*)pParam;
delete InputString;
return 0;
如果线程正常完成,它会很好地清理,但如果应用程序在线程运行时关闭,则会留下内存泄漏。在 VS2008 下调试没有检测到 VS2015 下的任何泄漏。从那时起,MFC 清理线程的方式是否发生了变化?
【问题讨论】:
如果在删除字符串之前线程被杀死,就会发生内存泄漏是很正常的。即使使用 VS2008,您也应该得到内存泄漏。无论如何,在程序退出之前正确停止线程会更干净,这样线程就可以进行所有必要的清理。 我也开始假设了。经过多年的拖延,我最近才升级到VS2015。调试器从未在相同的测试下记录任何泄漏。有什么方法可以检查析构函数中的开放线程吗? 我不知道,但您可以自己轻松完成。离开前等待pThread->m_hThread
句柄..
我已经有了一种使用 volatile bool 标志停止正在运行的进程的方法。我想我可以检查一下运行标志是否为真,如果是的话,如果他们确定要退出并且如果在 ID_OK 上从那里终止线程,则会弹出一个对话框。这不是一个优雅的解决方案,但我想它与“你想保存打开的文档”对话框没有太大区别。无论如何,非常感谢您的帮助。
如果您按照说明停止线程,则需要通过等待线程的句柄来等待线程完成设置标志后,线程仍在运行,这就是您绝对需要的原因等到线程真正完成。
【参考方案1】:
过程:
UINT ThreadProc(LPVOID pParam)
CMainFrame* pMainFrm = (CMainFrame*)AfxGetApp()->m_pMainWnd;
while(!pMainFrm->m_threadcancelflag )
return 0;
在标题中:
HANDLE hThread;
BOOL m_shutdownflag;
volatile BOOL m_threadcancelflag;
来源:
CWinThread *pThread;
if(!(pThread = AfxBeginThread(ThreadProc, (LPVOID)arr, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED)))
delete arr;
else
::DuplicateHandle(GetCurrentProcess(), pThread->m_hThread, GetCurrentProcess(), &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
pThread->ResumeThread();
覆盖 WM_CLOSE:
void CMainFrame::OnClose()
DWORD dwExitCode;
if(hThread)
::GetExitCodeThread(hThread, &dwExitCode);
if (dwExitCode == STILL_ACTIVE)
if(!m_shutdownflag)
m_shutdownflag = TRUE;
if (AfxMessageBox(_T("Running Process. \n\nQuitting now may result in a loss of data and/or incomplete database tables.\n\nTo quit anyway click \"OK\"\nTo allow the process to complete normally click \"Cancel\"."), MB_ICONSTOP | MB_OKCANCEL) == IDCANCEL)
m_shutdownflag = FALSE;
return;
else
m_shutdownflag = TRUE;
m_threadcancelflag = TRUE;
Sleep(500);
PostMessage(WM_CLOSE);
else
::CloseHandle(hThread);
CFrameWndEx::OnClose();
编辑:这是完整的解决方案......并且据记录,这是一个糟糕的程序员,他没有预见到意外并编写了一个不会自行清理并依赖操作系统来完成的程序程序应该做的。良好的编程习惯包括添加错误和异常处理以及自行清理。垃圾收集是编程的基础,尽管当程序在理想情况下结束时很容易做到,但如果没有,则涉及更多,但良好的编程习惯要求您必须始终预见到意外情况。我希望这段代码可以帮助别人。无论程序如何结束,这段代码都不会因为正在进行的线程而泄漏内存。
【讨论】:
以上是关于MFC 工作线程在意外关闭时未清理的主要内容,如果未能解决你的问题,请参考以下文章