VC10中CDialog内存泄漏
我们正在从 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;
}
内存使用量持续上升,并且我们拥有大约 30 个按钮的示例对话框泄漏了 10 兆字节。
请注意,上面是一个测试示例,其中我们删除了所有对话框处理代码,在我们的实际代码中,我们有一个派生类并使用 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;
}
我们在这里缺少什么?
We are upgrading from VC8 to VC10 and have found a number of memory leaks that seem to be CDialog related. The simplest example of this is demonstrated with the following code using a CDialog that just has a number of buttons. In VC10 this leaks, but in VC8 it doesn't:
for (int i = 0; i < 5000; ++i) {
CDialog* dialog = new CDialog;
dialog->Create(IDD_LEAKER, 0);
dialog->DestroyWindow();
delete dialog;
}
Memory usage keeps rising and the example dialog we have with about 30 buttons leaks 10s of Mb.
Note that the above is a test example where we have stripped out all of our dialog handling code, in our real code we have a derived class and use PostNcDestroy().
Oddly neither of the following code examples leak in either VC8 or 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;
}
What are we missing here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这似乎取决于 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() 实际上调用了这个整理事情:
This appears to be down to the way that MFC manages its handle maps:
What is the lifetime of a CWnd obtained from CWnd::FromHandle?
If you wait long enough for your application to become idle, you do get your memory back, i.e. it's not really a leak. However, as you have observed, while Visual C++ 2010 continues to consume more and more memory - until the maps are tidied in OnIdle() - this doesn't appear to happen in Visual C++ 2008.
Debugging an application containing your code does show that there are a lot more objects in the HWND temporary map in the VC 10 version than there are in the VC 9 version.
The handle map code (winhand.cpp) doesn't appear to have changed between the two versions but there's lots of code in MFC that uses it!
Anyway, assuming that you really want to run your program like this - I guess you're running in some kind of automated mode? - then you'll want to force the garbage collection at appropriate intervals. Have a look at this entry on MSDN:
http://msdn.microsoft.com/en-us/library/xt4cxa4e(v=VS.100).aspx
CWinThread::OnIdle() actually calls this to tidy things up: