1. 程式人生 > >非模態對話方塊的指標釋放的理解

非模態對話方塊的指標釋放的理解

最近專案出現記憶體洩漏的問題,找到非模態對話方塊的指標釋放問題,尤其是很多層對話方塊的釋放問題。

每個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 ,除非你的類是單模式的。