然后在需要使用查找功能的时候,用下面的代码响应:
void CTestSdiView::OnFindReplace() { // TODO: Add your command handler code here if (m_pFRDlg == NULL) { m_pFRDlg = new CFindReplaceDialog(); TRACE("----0xx/n", m_pFRDlg); m_pFRDlg->Create(TRUE, _T("hello"), _T(""), FR_DOWN, this); } m_pFRDlg->ShowWindow(SW_SHOW); } 在查找下一个和关闭查找对话框的时候,用下面的代码响应: LONG CTestSdiView::OnFindReplace(WPARAM wParam, LPARAM lParam) { CFindReplaceDialog *pDlg = CFindReplaceDialog::GetNotifier(lParam); if (pDlg != NULL) { if (pDlg->IsTerminating()) { // delete m_pFRDlg; m_pFRDlg = NULL; } else if (pDlg->FindNext()) { } } return 0; } 后面这段代码,在检测到关闭查找对话框的时候,直接将m_pFRDlg指针置空,这样刚new出来的内存不就无法可寻了。下次再需要查找的时候,又是重新new一块新的内存。于是,我想我发现了一个大问题——内存泄漏了 。所以我就加了上面注释掉的 delete m_pFRDlg;这句。不过结果就是关闭查找对话框后,程序死掉。
我就纳闷了,想不通了。猜测应该是内存被释放了多次。
接着,我在前面的代码中加入了:
TRACE("----0xx/n", m_pFRDlg);用来打印每次new出来的内存地址,结果发现:每次申请到的是同一块地址(同一个地址)。
这证明了上次new出来的地址已经确确实实被释放了。可是,在哪里呢? 后来,还是Google搜索获得了有用的信息:
……
到这时,清除工作已经完成了一半,屏幕上的窗口已经不见了!但是别忘了,在内存中还有一个c++窗口对象.让我们再看看c++对象清除的过程:当窗口被取消时,窗口最后发送的一个消息是WM_NCDESTROY.它缺省的消息处理函数CWnd::OnNcDestroy把c++窗口对象与句柄HWND分离,并调用一个很重要的虚函数PostNcDestroy.这个函数是搞清窗口对象清除的关键.Cwnd中的PostNcDestroy什么都不做.有些MFC窗口类会重载它,并加入delete this代码删除c++对象.这些窗口类常常是以new操作符建立在堆中的.由于重载了PostNcDestroy,使窗口有自动清除功能.因此,我们不用关心清除问题了.另外的一些MFC窗口类一般是以变量形式创建的,MFC没有为也没必要为它们重载PostNcDestroy函数. …… 不具备自动清除功能的窗口类,一般在堆栈中创建或嵌入于其它c++对象中: 所有标准的Windows控件类(如CStatic, CEdit, CListBox等等) 由CWnd类直接派生出来的子窗口对象(如用户定制的控件) …… 所有的Windows通用对话框(除CFindReplaceDialog) …… 可见,如果CWnd的子类重载了PostNcDestroy虚函数,并且在内部调用了delete this语句,就可以具有自动清除的功能,并且CFindReplaceDialog应该是已经有的了。 我搜索MFC的源代码,也确实发现了如下代码: void CFindReplaceDialog::PostNcDestroy() { ASSERT(m_hWnd == NULL); delete this; } 至此,问题明了。这个问题之所以耗费了不少的时间还有别人的帮助,我觉得就是自己之前从来没有想过C++对象会有“垃圾回收机制”,所以思维的定势就限制了自己的思路。最终仍是在别人的帮助下才找到了原因所在。