c++ - 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);
}
解决方案
调用 free()(或 delete)时,堆内存通常不会返回给操作系统。它保留在堆中。另请参阅此答案。因此,在第一次填充/删除所有操作时,您将看到分配的内存增加。但在随后的循环中,内存使用应该相当稳定。
微软的 MFC 库已经存在了十多年,如果CListCtrl::DeleteAllItems()中存在内存泄漏,它会在 90 年代被发现。
您可以通过一些 API 调用来检查程序内的内存使用情况。
内存泄漏可能是由这一行引起的:
ok = m_ListCtrl.SetItemData(row, (DWORD_PTR)iSecs);
在 MFC 中,项目数据是用户清理的责任。在调用 API 删除列表项之前,您需要遍历列表中的每个项目以释放(或删除)用户数据。当然,您也可以通过其他方式释放分配的数据。
当您的程序不断地从列表中添加和删除项目时,它会泄漏与每个列表条目关联的 ItemData(s)。
推荐阅读
- c++ - C ++“不允许不完整类型”尝试在类中创建函数数组
- python - 如何清理字符串数据
- date - HQL 中的强制转换和比较表达式
- python - 在python中按条件过滤并绘制批处理图
- intellij-idea - IntelliJ - 如何显示和隐藏正确的面板?
- google-app-engine - Google Cloud Platform 及其应用程序是否符合 GDPR?
- javascript - 如何以最有效的方式编写一个最便宜的StoreForRecipe 函数?
- discord.py - 如何检查角色是否由集成自动管理?
- flutter - 颤动中儿童内部的验证错误
- nativescript - 将 POST 响应保存为 NativeScript 中的文件