CD10中的CDialog内存泄漏

lil*_*rne 7 mfc memory-leaks cdialog visual-studio-2010 visual-c++

我们正在从VC8升级到VC10,并且发现了许多与CDialog相关的内存泄漏.下面的代码使用一个只有许多按钮的CDialog来演示最简单的例子.在VC10中泄漏,但在VC8中它不会:

for (int i = 0; i < 5000; ++i) {
  CDialog* dialog = new CDialog;
  dialog->Create(IDD_LEAKER, 0);
  dialog->DestroyWindow();
  delete dialog;
}
Run Code Online (Sandbox Code Playgroud)

内存使用率不断上升,我们使用大约30个按钮的示例对话框泄漏了Mb的10s.

请注意,上面是一个测试示例,我们已经删除了所有对话框处理代码,在我们的实际代码中,我们有一个派生类并使用PostNcDestroy().

奇怪的是,VC8或VC10中都没有以下代码示例泄漏:

CDialog* dialog = new CDialog;
for (int i = 0; i < 5000; ++i) {
  dialog->Create(IDD_LEAKER, 0);
  dialog->DestroyWindow();
}
delete dialog;

for (int i = 0; i < 5000; ++i) {
  CDialog* dialog = new CDialog;
  delete dialog;
}
Run Code Online (Sandbox Code Playgroud)

我们在这里失踪了什么?

Nic*_*ick 7

这似乎取决于MFC管理其句柄映射的方式:

从CWnd :: FromHandle获得的CWnd的生命周期是多少?

如果你等待的时间足以让你的应用程序变得空闲,那么你确实会恢复你的记忆,即它不是真正的泄漏.但是,正如您所观察到的,虽然Visual C++ 2010继续消耗越来越多的内存 - 直到地图在OnIdle()中整理 - 这似乎不会发生在Visual C++ 2008中.

调试包含代码的应用程序确实显示VC 10版本的HWND临时映射中的对象比VC 9版本中的对象多得多.

句柄映射代码(winhand.cpp)似乎没有在两个版本之间发生变化,但MFC中有很多代码使用它!

无论如何,假设你真的想要像这样运行你的程序 - 我猜你在某种自动模式下运行? - 然后你会想要以适当的间隔强制垃圾收集.在MSDN上查看此条目:

http://msdn.microsoft.com/en-us/library/xt4cxa4e(v=VS.100).aspx

CWinThread :: OnIdle()实际上调用它来整理东西:

AfxLockTempMaps();
AfxUnlockTempMaps(/*TRUE*/);
Run Code Online (Sandbox Code Playgroud)