2017-04-13 66 views
0

這是否有意義,如果我說析構函數是存在突然沒有得到完成的機會,因爲UI窗口已被取消,當所有這一切發生在同一(主)線程?析構函數沒有足夠的時間來完成?

當我按在對話框中的「取消」,我想釋放與列表時,相關的記憶:)

CMyListCtrl::~CMyListCtrl() 
{ 
    ItemData* pItemData; 
    int nItems = GetItemCount(); <- errors out here and it is called 
    for(int i=0; i<nItems; i++) 
    { 
     pItemData = (ItemData*)GetItemData(i); 
     if(pItemData != NULL) 
      delete pItemData; 
    } 
} 

我OnCancel(處理程序如下,其中

LONG CSetupDlg::OnCancel(UINT wParam, LONG lParam) 
{ 
    ((CSetupDoc *)GetActiveDocument())->Exit(); 
    return 0; 
} 

void CSetupDoc::Exit() 
{ 
    GetDocTemplate()->CloseAllDocuments(TRUE); 
} 

析構函數主要是因爲CloseAllDocuments()調用而被調用,但在嘗試清理時它會在中間被炸掉,我甚至無法通過它。如果我評論CloseAllDocuments()調用,那麼窗口永遠不會被銷燬,析構函數也不會被調用,所以析構函數肯定與這個函數綁定在一起,並且它們顯然是在同一個線程中。

爲什麼它聲稱好像底層窗口已經奇蹟般地消失了?

我得到的錯誤信息是MyApp has triggered a breakpoint,我無法再進一步瞭解它。

+0

請提供更多代碼。沒有看到每一行被執行,都很難調試。 – UniversE

+0

請指出(至少在標籤中)你正在做什麼。這幾乎可以肯定是Windows,但那麼什麼環境? MFC? ATL? –

+1

我不認爲直到窗口被銷燬才調用析構函數,因此訪問控件已經太晚了。我不知道爲什麼這會與'CloseAllDocuments'連接。 –

回答

1

我發佈瞭解決問題的正確答案。我們需要釋放LVN_DELETEITEM消息處理程序中的列表內存(即使OnDestroy()沒有工作,列表已經消失)。

void CMyListCtrl::OnLvnDeleteitem(NMHDR *pNMHDR, LRESULT *pResult) 
{ 
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); 
    // TODO: Add your control notification handler code here 

    ItemData* pItemData = (ItemData*)pNMLV->lParam; 
    delete pItemData; 

    *pResult = 0; 
} 

至於析構函數被斷言/不進一步執行是因爲GetItemCount()名錄窗口運行,但因爲它已經被破壞,其行爲未知。

2

看來,您可能不會從析構函數中訪問列表控件的函數。我不記得這是否是一個規則,或者是否由於代碼中的其他奇怪情況而發生。通常情況下,你可能無法做到這一點。

在任何情況下,您可能都想嘗試在列表控件的WM_DESTROY消息的處理程序中進行清理,而不是使用列表控件的析構函數。

+0

看起來像是這樣,我幾乎想說我已經看到過這種行爲。但從技術上講,當控件是列表控件的析構函數時,它仍然不會被銷燬。 – zar

+1

zar是正確的 - 在您的類中清除重寫'CMyListCtrl :: DestroyWindow',然後在清理完成時調用'CListCtrl :: DestroyWindow'。你通常不會在MFC析構函數中做任何事情,因爲CWnd對象封裝了數據,但不等同於實際的窗口。 –

+1

我建議你在你要添加的'WM_DESTROY'處理函數上放一個斷點;然後當它被命中時,創建一個數據斷點(在斷點窗格上),該條件是'listcontrol-> m_hWnd'的變化。在某些時候,變量將變爲空,並且執行將在那裏暫停。然後,您可以單獨參與每個相關步驟,以便您更好地掌握整個過程的發生。順便說一句,如果你「甚至不能通過它」,可能是你沒有他對應的符號加載。 – sergiol

1

您等待時間太長。在析構中已經太晚了。此時,窗口句柄(m_hWnd)不再有效,Windows已銷燬該窗口。此時列表控件中的項目全部被刪除。正如其他人指出的那樣,將您自己的CMyListCtrl :: OnDestroy()函數和ON_WM_DESTROY()宏添加到您的CMyListCtrl消息映射中。將清理代碼放入OnDestroy()函數中。

+0

嘗試過,雖然它沒有斷言,但GetItemCount()返回零,對話框已經消失,所以它看起來像列表已被銷燬。 – zar

+0

哦我現在記得,它已經刪除WM_DELETEITEM! – zar

+0

通常,我不這樣做。通常,集合存在於控件的生命週期之外。在這種情況下,當我調用SetItemDataPtr()時,我將設置索引,指針,迭代器或其他集合中不需要由控件清理的項目的引用。 –

相關問題