2009-06-03 77 views
7
// CMyDialog inherits from CDialog 
void CMyFrame::OnBnClickedCreate() 
{ 
    CMyDialog* dlg = new CMyDialog(); 
    dlg->Create(IDD_MYDIALOG, m_thisFrame); 
    dlg->ShowWindow(SW_SHOW); 
} 

我敢肯定,这泄漏。我真正要问的是:MFC中是否有任何“魔术”,当对话被销毁时会进行对话清理。如果dlg不是一个指针而是在堆栈中声明的话,它会如何工作 - 当dlg超出范围时,析构函数是不是会销毁该窗口。这是在MFC内存泄漏

回答

12

是的,这是内存泄漏你的情况,但你可以避免内存泄漏的情况下,通过使用重写PostNcDestroy在堆上分配非模态对话框。

对话框不是为自动清理而设计的(其中主框架窗口,查看窗口在这里)。 如果您想为对话框提供自动清理功能,那么您必须重写派生类中的PostNcDestroy成员函数。要将自动清理添加到您的班级,请致电您的基础班级,然后执行delete this。要从您的课程中删除自动清理,请直接拨打电话CWnd::PostNcDestroy,而不是直接基本类中的PostNcDestroy成员。

void MyDialog::PostNcDestroy() 
{ 

    CDialog::PostNcDestroy(); 
    delete this; 
} 

这是如何工作(从MSDN):

当销毁一个Windows窗口,发送到 窗口 最后的Windows消息是WM_NCDESTROY。该消息的默认 CWnd句柄 (CWnd :: OnNcDestroy)将从C++对象中分离出 HWND,并调用 虚拟函数PostNcDestroy。某些 类将该函数覆盖到 删除C++对象。

“删除此”将释放与C++对象关联的任何C++ 内存。 即使默认的CWnd 析构函数调用的DestroyWindow如果 m_hWnd不是NULL,这不会导致 无穷递归,因为手柄 将在 清理阶段分离和NULL。

您也可以参考MSDN(Destroying Window Objects)了解更多详情。

注:

这适用于可以在分配模式对话框。

3

是的,这是一个泄漏。是的,如果对象被堆栈分配,窗口将被销毁。使用对话框作为堆栈分配对象是典型的模式对话框 - 您调用一个方法将对话框显示为模式窗口,并且该方法仅在对话框关闭并且对象在此之后销毁时才会返回。

+0

谢谢。我忘了说这是一个无模式对话框。我假设在这种情况下清理对话框对象必须是一个成员变量 - 所以它可以在框架析构函数中销毁/取消分配。 – Richard 2009-06-03 11:10:15

2

如果你手动调用Create一个对话框,你必须手动Destroy它。
使用时DoModal()这是没有必要的。

MSDN

使用的CWnd :: DestroyWindow而功能 摧毁由 创建一个对话框,创建功能。