首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MFC CView (CFormView)破坏崩溃

MFC CView (CFormView)破坏崩溃
EN

Stack Overflow用户
提问于 2015-09-18 21:03:51
回答 3查看 2K关注 0票数 11

根据这个堆栈溢出问题:

以编程方式退出MFC应用程序的正确方法是什么?

我正在使用AfxGetMainWnd()->PostMessage(WM_CLOSE,0,0);退出一个MFC程序。(SDI,CFrameWnd包含一个带有两个CFormViews的CSplitterWnd )

正如预期的那样,这将调用DestroyWindow()

我面临的问题是,在派生的CFormView销毁之后,如MSDN所示:

在对非自动清理对象调用DestroyWindow之后,C++对象仍然存在,但是m_hWnd将为NULL。[MSDN]

现在调用CView析构函数,此时它执行

代码语言:javascript
复制
CDocument::RemoveView()...
CDocument::UpdateFrameCounts()

它在以下断言中失败:ASSERT(::IsWindow(pView->m_hWnd));

我检查过了,在前面调用的派生CView析构函数中,CView已经设置为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()

现在,在这个函数中

代码语言:javascript
复制
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_hWndNULL

编辑3:

我想出了问题所在:

第一个视图的析构函数正在删除一个未初始化的指针,即UB。这会让破坏者挂起来,永远也不会完成。

通常,只有在完成第一个视图时才调用第二个视图的析构函数。但在这种情况下,它仍然在执行,尽管第一个从未完成。

由于从未调用过第一个视图基类析构函数,因此从未为第一个视图调用此函数:

代码语言:javascript
复制
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.中移除的

这意味着当第二个视图析构函数完成时,如下所示:

代码语言:javascript
复制
void CDocument::UpdateFrameCounts()
     // assumes 1 doc per frame
{
    // walk all frames of views (mark and sweep approach)
    POSITION pos = GetFirstViewPosition();
    while (pos != NULL)
    {
...

NULL**,被认为是,但它不是。导致坠机。**

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-09-30 17:59:53

问题已解决,请参阅问题中的编辑3以获得解决方案。

票数 0
EN

Stack Overflow用户

发布于 2015-09-23 16:52:04

我认为你关闭框架的方式不是问题所在。我的猜测是,您手动销毁其中一个视图,而应该让MFC删除它们(您可能在其中一个视图上调用了DestroyWindow )。

票数 2
EN

Stack Overflow用户

发布于 2015-09-19 17:25:07

打电话给::PostQuitMessage(0);关闭应用程序。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32661010

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档