2017-04-13 84 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()时,我将设置索引,指针,迭代器或其他集合中不需要由控件清理的项目的引用。 –

相关问题