非模态对话框的指针释放的理解

最近项目出现内存泄漏的问题,找到非模态对话框的指针释放问题,尤其是很多层对话框的释放问题。

每个CPP文件加上:

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

 

这段代码会检测到new出来的指针,没有释放的内存泄漏。

关于非模态对话框的指针释放的问题,找了一些资料,总结如下:就是父子对话框的时候,父对话框用指针创建一个对话框:

 

父对话框里

定义:Cdialog1* m_dialog1;//Cdialog1*是子对话框的类

创建并显示:

 m_dialog1 = new Cdialog1();
 m_dialog1->Create(IDD_DIALOG1 ,this);
 m_dialog1->ShowWindow(SW_SHOW);

 

那究竟在哪里释放m_dialog1 比较合理呢?

这里面要明白窗口的一些机制,每一个窗口关闭的时候(用CDialog::OnOk()或者CDialog::OnCancel()),只是隐藏了窗口而已,并没有销毁窗口。所以窗口还会执行CDialog::OnDestroy()销毁窗口,一旦执行完这个,窗口的句柄就会m_Hwnd=NULL,最后才是执行析构函数。窗口的关闭和销毁过程是这样的一个顺序。

 不信拉一个窗口出来试试就知道了。

 

可是,子窗口是在父窗口用m_dialog1  =  new Cdialog1()出来的,指针对象是在Heap(堆)的,一定要释放,不然内存泄漏,虽然窗口句柄在关闭整个程序的时候,会自动从父窗口—子窗口的顺序OnDestory(),可是指针对象不会自动就销毁了。简而言之,就是句柄没有了,窗口指针对象还在(句柄只是指针的众多数据里的一员)。

可是,在哪里释放才是合适合理的呢。

测试1:

在子对话框里面OnDestory()主动调用delete this,释放对象,delete this会触发析构函数,看起来顺序似乎和上面说到的销毁窗口的机制一样,可是就会报出错误:

Warning: calling DestroyWindow in CDialog::~CDialog --OnDestroy or PostNcDestroy in derived class will not be called.

原因是:OnDestory函数要执行完返回才会销毁句柄,如果没有执行完就去delete this,会触发析构函数,进入析构函数前没有销毁窗口就会报这样的警告。

 

测试2:我们在父窗口里释放指针对象,因为我们是在这里new出来的,在这里delete才对。

这里注意到,基于对话框的程序主窗口是没有析构函数的,自己加上会报错,原因不明。

CtestptDlg是主对话框的类,所以这里放在OnDesotry()执行销毁下一级窗口和释放指针。

void CteseptDlg::OnDestroy()
{
 CDialogEx::OnDestroy();

 // TODO: 在此处添加消息处理程序代码
 if (m_dialog1 != NULL)
 {
  m_dialog1->DestroyWindow();
  HWND hmydialog1 = m_dialog1->GetSafeHwnd(); //这里子对话框句柄肯定没有了,看上一句
  delete m_dialog1;
  //m_dialog1 = NULL;//这样 = delete
 }

 

除了主窗口比较特殊,其他的窗口释放都应该放在析构里面 。

Cdialog1::~Cdialog1()
{
 if (pdialog2 != NULL)
 {
  pdialog2->DestroyWindow();//这里如果还有下一级子对话框,会自动往下一级destory
  HWND hmydialog1 = pdialog2->GetSafeHwnd(); //这里子对话框句柄肯定没有了,看上一句
  delete pdialog2;
  //m_dialog1 = NULL;//这样 = delete
 }
}

 

pdialog2是Cdialog下一级的对话框,如果我们一下关闭了整个主窗口,执行pdialog2->DestroyWindow()前已经执行过一次了,这里再写一次的话,实际是执行不成功的,返回FALSE。不过为了写法统一,还是这样写吧。这里说明窗口可以重复DestoryWindow(),可是指针不能重复delete。

 

还有一些东西,如果在类中要delete自己对象呢?这里最好发送消息给父窗口,来执行销毁自己和释放指针,而不要自己在类里面delete this ,除非你的类是单模式的。

你可能感兴趣的:(MFC,&&,C++)