首页 > 解决方案 > MFC C++ CListCtrl - 删除所有项目不会回收内存

问题描述

根本不是 MFC 方面的专家,但我已经参与了一个项目,以在我们的一个应用程序中改进 GUI。我正在使用 CListCtrl 构建一个对话框并看到内存问题,即使我正在显示的列表通常包含不超过 200 行。有 4 列,我使用 SetItemData 为每一行附加一个关联的 int 值,以便进行过滤。

当我过滤时,我首先调用 DeleteAllItems() 重新填充列表,然后循环以仅填充通过过滤器的数据。当我在系统任务管理器对话框的“性能”选项卡中查看时,我看到对话框打开时已占用内存。似乎比我想象的要多,但无论如何。根据任务管理器性能选项卡,当我过滤时,如果所选过滤器没有显示任何内容,则系统永远不会回收内存。当我更改过滤器以显示一些行时,我看到占用了更多内存。我从来没有看到内存回馈给系统。如果我继续过滤,我最终会看到内存使用量几乎完全使用,并且我会看到 MFC 提出的内存不足对话框。

当我只是在数据的完整(未过滤)视图中上下滚动很多时,我也看到了这个内存不足对话框。对于每次滚动,重新绘制列表控件有点慢,并且性能选项卡中的内存使用量上升,即使我没有添加任何数据。

有人对这里可能发生的事情有感觉吗?我现在很难过。以下基本上是我在我的代码中所做的。我没有以其他方式管理视图:

m_ListCtrl.DeleteAllItems();
for (int i=0; i<mylist.size(); i++)
{
    // here I get all the data from the current record in mylist, one of them being an int value iSecs.
    ...

    // insert data item
    int row = m_ListCtrl.InsertItem(i, sTimeStamp.c_str());
    BOOL ok = m_ListCtrl.SetItem(i, 1, sErrorCode.c_str());
    ok = m_ListCtrl.SetItem(i, 2, sErrorLevel.c_str());
    ok = m_ListCtrl.SetItem(i, 3, sDescription.c_str());
    // set the timestamp seconds as item data for later filtering for display
    ok = m_ListCtrl.SetItemData(row, (DWORD_PTR)iSecs);
}

标签: c++visual-studio-2010memory-leaksmfcclistctrl

解决方案


调用 free()(或 delete)时,堆内存通常不会返回给操作系统。它保留在堆中。另请参阅此答案。因此,在第一次填充/删除所有操作时,您将看到分配的内存增加。但在随后的循环中,内存使用应该相当稳定。

微软的 MFC 库已经存在了十多年,如果CListCtrl::DeleteAllItems()中存在内存泄漏,它会在 90 年代被发现。

您可以通过一些 API 调用来检查程序内的内存使用情况。

内存泄漏可能是由这一行引起的:

ok = m_ListCtrl.SetItemData(row, (DWORD_PTR)iSecs);

在 MFC 中,项目数据是用户清理的责任。在调用 API 删除列表项之前,您需要遍历列表中的每个项目以释放​​(或删除)用户数据。当然,您也可以通过其他方式释放分配的数据。

当您的程序不断地从列表中添加和删除项目时,它会泄漏与每个列表条目关联的 ItemData(s)。


推荐阅读