【问题标题】:A sleep in thread causes memory leak线程睡眠导致内存泄漏
【发布时间】:2011-09-23 05:12:59
【问题描述】:

我查看了我祖先的代码,发现在以下情况下存在泄漏:

1) 启动应用程序
b) 应用启动后,4秒内关闭应用

泄露消息:

f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\thrdcore.cpp(306) : {58509} client block at 0x016DFA30, subtype c0, 68 bytes long.

随后,我通过代码,在工作线程的控制功能休眠4秒时找出了可疑的原因。

测试程序:

UINT InitThread(LPVOID pParam)
{
      Sleep(4000);  //4000 is the default value, it reads from a registry key.
      CMyMFCTestProjectDlg* pTest = (CMyMFCTestProjectDlg*)pParam;
      pTest->DoSomething();  
      return 0;  //--> Exit thread
}

BOOL CMyMFCTestProjectDlg::OnInitDialog() {
...
AfxBeginThread(InitThread, this);
...
}

如果我减少/删除睡眠计时器,泄漏将得到解决。
但是,我想知道它是如何发生的。是由于工作线程还是 GUI 线程终止? GUI线程后工作线程退出会导致这个问题吗?

任何人都可以通过帮助我解释这一点来振作我的一天吗?我迷路了……

【问题讨论】:

  • 这不是睡眠。您需要发布更多代码。包含 Sleep 的线程是做什么的?
  • @Matt H:线程内还有一些其他代码。这是一个“休眠线程”,可以提供延迟执行剩余代码的选项。让我尝试编辑代码...

标签: c++ multithreading mfc memory-leaks


【解决方案1】:

您应该在进程消失之前优雅地关闭线程。您可以让主线程等待其他线程退出,也可以让主线程通知其他线程退出。

【讨论】:

  • '您应该在进程消失之前优雅地关闭线程'。为什么?操作系统非常擅长停止线程。有许多关闭问题的情况实际上是由于尝试发出信号以退出并等待它们退出而引起的。如果线程不合作,(可能卡在某些阻塞 API 上),主线程也会卡住,并且不会到达本来会终止所有线程的 ExitProcess()。
【解决方案2】:

听起来工作线程在您的应用关闭后没有机会正确关闭自己,因为进程在退出之前就结束了。操作系统通常非常擅长自行清理资源,因此它可能不是问题。但是,最好在允许应用程序关闭之前等待该线程退出。虽然听起来这会导致您的应用程序关闭延迟 4 秒。

如果这是不可接受的,您将不得不向线程添加一些机制,以接收来自应用程序主线程的关闭事件。例如,如果您将工作线程“睡眠”替换为事件的 WaitForSingleObject:

DWORD res = WaitForSingleObject(
    shutdownEvent,
    4000); // timeout
if(res == WAIT_OBJECT_0)
{
    // received the shutdownEvent, exit
    return 0;
}
// The delay has elapsed, continue with rest of thread.
. . .

然后,当您在主线程中关闭时,设置事件,然后等待线程退出,它应该几乎立即退出:

SetEvent(this->shutdownEvent);
WaitForSingleObject(pThread->m_hThread, INFINITE); // pThread is returned from AfxBeginThread

【讨论】:

  • 关闭应用程序通常涉及调用 ExitProcess()。此 API 停止除调用者之外的所有正在运行的线程,并在 DLL 分离后停止。显式等待其他进程线程退出并不是压倒性的要求——操作系统将毫无问题地阻止它们,无论它们处于何种状态——阻塞、睡眠或在另一个 CPU 上运行,操作系统并不关心。许多关闭问题实际上是导致显式等待辅助线程退出,因此阻止主线程到达 ExitProcess() 并因此关闭应用程序。
【解决方案3】:

68 字节?

如果应用程序确实关闭了,即。已从任务管理器“应用程序”和“进程”中消失,并且此“泄漏”的唯一影响是在提前关闭时发出调试消息,只需关闭调试并忘记它。

这可能是 MFC 关闭的缩写,某些结构在关闭期间无法安全释放,并留给操作系统清理。

由于 99.9% 的应用程序不会持续重新启动/停止,因此关闭时的 68 字节泄漏,即使没有清理,也不会在重新启动间隔之间以任何明显的方式影响 Windows 机器的运行每个“星期二补丁”强制执行。

我敢肯定,您还有更多具有更严重影响的错误需要处理。如果没有,你可以来点我的!

Rgds, 马丁

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    • 2022-11-06
    • 2019-10-21
    • 2015-07-06
    • 2014-06-07
    • 2013-11-20
    相关资源
    最近更新 更多