【问题标题】:How to insure important messages are handled before quitting如何确保重要消息在退出前得到处理
【发布时间】:2015-12-07 20:49:00
【问题描述】:

我有一个 Win32 MFC 应用程序,它创建了一个侦听 RS232 端口的线程。当接收到新数据时,侦听器线程使用new 分配内存并使用PostMessage 将消息发布到窗口。这进行得很好,窗口处理传入的数据并根据需要使用delete 删除内存。当我的程序关闭时,我注意到一些小的内存泄漏。我的怀疑是,在用户关闭程序并且线程在该内存被正确删除之前关闭时,正在发布一两条最终消息并且仍在消息队列中。有没有办法可以确保在程序关闭之前发生某些事情?我可以确保消息队列是空的,或者至少已经处理了其中一些重要消息吗?我试过在析构函数和类似的东西中查看WaitForInputIdlePeekMessage。关于解决这个问题的好方法有什么想法吗?

【问题讨论】:

  • 你为什么在乎?应用程序正在关闭,一旦进程终止,操作系统将回收所有分配的内存。
  • 除了在析构函数中释放资源外,不要做任何事情。你正在为自己招来很多痛苦。 (死锁和竞争条件很难解决)如果您需要确保消息传递,请使用SendMessage
  • 太棒了!我喜欢听到我可以放手。但是我的印象是动态分配内存而不释放它是一种糟糕的形式。您提出了一个很好的观点,即操作系统在退出后会回收内存,但我只是认为,对于我所知道的每一次内存泄漏,可能还有其他一些我还不知道的可能导致更大的问题,或者这可能会使其他更严重bug 更难找到。我很惊讶你们很高兴我能不理会这件事。你能详细说明一下吗?
  • 有点争议;一些程序员确实更喜欢在退出之前释放所有内容,这样如果他们有真正的内存泄漏,他们就可以分辨出来。另一方面,在某些情况下,它可能会导致非常缓慢的关机。在您的情况下,我认为跟踪这些内存分配是合理的 - 将它们放在链表或其他东西中 - 这样您就可以在退出时释放它们。

标签: winapi mfc


【解决方案1】:
  1. 我 100% 同意所有分配的内存都应该显式释放。 (就像您应该修复所有编译器警告一样)。这消除了诊断噪音,让您能够快速发现真正的问题。

  2. 根据 Harry Johnston 的建议,我会将所有新数据推送到某种队列中,然后简单地发布“检查队列”命令,在消息处理程序中删除和释放数据。这样您就可以在退出前轻松释放队列中剩余的所有内容。

【讨论】:

    【解决方案2】:

    对于小型实用程序,这种泄漏可能是可以接受的 - 但它可能涵盖其他不太良性的原因。

    PostMessage 不保证交付。所以其他选项是

    • 使用阻塞SendMessage
    • 将数据添加到双端队列,使用 Post Message 通知接收者有新数据可用

    (远程代码审查:如果PostMessage返回false,是否立即删除内存?)

    【讨论】:

    • 我没有检查 PostMessage 的返回码我应该然后删除内存。感谢您的建议!
    【解决方案3】:

    那些认为不用担心的人是有道理的。该过程即将结束,操作系统将释放所有内存,因此花时间清理没有太大意义。

    但是,这确实会产生噪音,可能会掩盖正在进行的内存泄漏,这可能会在您的应用程序退出之前成为真正的问题。这也意味着您的程序将更难变成以后可以合并到另一个应用程序中的库。

    我喜欢编写干净的关闭代码,然后在 opt 构建中添加提前退出以跳过不必要的工作。因此,您的调试版本将告诉您真正的泄漏,并且您的用户将获得响应退出。

    要干净利落地做到这一点:

    您需要一种方法让主线程告诉侦听器线程退出(或至少停止侦听)。否则,您将始终有一个小的机会窗口,其中主线程即将退出,就像侦听器进行另一个分配一样。主线程需要知道侦听器线程已接收并遵守此消息。只有这样,主线程才能通过队列来释放与最后一条消息相关的所有内存,并且知道不会有更多消息到达。

    不要使用 TerminateThread,否则你会遇到更多问题!如果监听线程正在等待一个代表串口的句柄,那么你可以让它等待两个句柄:串口句柄和事件句柄。当主线程希望监听器退出时,它可以引发事件。侦听器线程可以引发不同的事件来表示它已停止侦听。

    当主线程获得 WM_QUIT 时,它应该引发事件来告诉监听器退出,然后等待监听器线程完成的事件,然后使用 PeekMessage 拉取监听器在它停止之前发布的任何消息并释放与它们相关的内存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-07
      • 1970-01-01
      • 1970-01-01
      • 2013-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多