2009-06-03 97 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而功能 摧毀由 創建一個對話框,創建功能。