[英]MFC CView (CFormView) destruction crash
根據這個stackoverflow問題:
我正在使用AfxGetMainWnd()->PostMessage(WM_CLOSE,0,0);
退出MFC程序。 (SDI,CFrameWnd包含帶有兩個CFormViews的CSplitterWnd)
正如所料,這稱為DestroyWindow()
。
我面臨的問題是在導出的CFormView銷毀之后,根據MSDN:
在非自動清理對象上調用DestroyWindow后,C ++對象仍然存在,但m_hWnd將為NULL。 [ MSDN ]
現在調用CView
析構函數,然后它就完成了
CDocument::RemoveView()...
CDocument::UpdateFrameCounts()
它在以下斷言上失敗: ASSERT(::IsWindow(pView->m_hWnd));
我檢查過,在之前調用的派生CView析構函數中, m_hWnd
已經設置為NULL。
我究竟做錯了什么 ?
編輯:
這是一個圖表,說明我想發送WM_CLOSE消息而不是WM_QUIT的原因。
我認為這個答案存在於MSDN技術說明中 ,但我無法弄清楚。
編輯2:
事物被調用的順序:
1- AfxGetMainWnd()->PostMessage(WM_CLOSE,0,0);
2- Derived CFrameWnd::OnClose()
3- CFrameWnd::OnClose()
它調用CWinApp::CloseAllDocuments(BOOL bEndSession);
調用CDocManager::CloseAllDocuments(BOOL bEndSession)
它調用CDocTemplate::CloseAllDocuments(BOOL)
調用CDocument::OnCloseDocument()
現在,在這個功能
while (!m_viewList.IsEmpty())
{
// get frame attached to the view
CView* pView = (CView*)m_viewList.GetHead();
ASSERT_VALID(pView);
CFrameWnd* pFrame = pView->EnsureParentFrame();
// and close it
PreCloseFrame(pFrame);
pFrame->DestroyWindow();
// will destroy the view as well
}
所以我們看到CWnd::DestroyWindow()
被調用,所以:
4- Derived CFormView destructor
5- CScrollView::~CScrollView()
6- CView::~CView()
調用CDocument::RemoveView(CView* pView)
調用CDocument::OnChangedViewList()
調用CDocument::UpdateFrameCounts()
這里崩潰了: ASSERT(::IsWindow(pView->m_hWnd));
因為pView->m_hWnd
是NULL
...
編輯3:
我弄清楚問題是什么:
第一個視圖的析構函數是刪除未初始化的指針,即UB。 這使析構函數掛起並永遠不會完成。
通常,第二個視圖的析構函數僅在完成第一個視圖時被調用。 但在這種情況下它仍然被執行,雖然第一個從未完成。
由於從未調用過第一個視圖基類析構函數,因此從未為第一個視圖調用此函數:
void CDocument::RemoveView(CView* pView)
{
ASSERT_VALID(pView);
ASSERT(pView->m_pDocument == this); // must be attached to us
m_viewList.RemoveAt(m_viewList.Find(pView));
pView->m_pDocument = NULL;
OnChangedViewList(); // must be the last thing done to the document
}
我們可以看到視圖已從m_viewList
刪除 。
這意味着當第二個視圖析構函數完成時,在:
void CDocument::UpdateFrameCounts()
// assumes 1 doc per frame
{
// walk all frames of views (mark and sweep approach)
POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
...
pos應該是NULL
,但事實並非如此。 導致崩潰的原因。
我認為你關閉框架的方式不是那里的問題。 我的猜測是你手動銷毀其中一個視圖,而你應該讓MFC刪除它們(你可能在其中一個上調用了DestroyWindow)
Call ::PostQuitMessage(0);
關閉應用程序。
問題已解決,請參閱問題解答中的編輯3。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.