没有足够的时间让析构函数完成?
Posted
技术标签:
【中文标题】没有足够的时间让析构函数完成?【英文标题】:Not enough time for destructor to finish? 【发布时间】:2017-04-13 20:31:08 【问题描述】:如果我说析构函数突然存在而没有机会完成,因为当所有这些都发生在同一个(主)线程中时 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
,我无法再继续下去了。
【问题讨论】:
请提供更多代码。没有看到执行的每一行,很难调试。 请说明(至少在标签中)您正在做什么。几乎可以肯定是Windows,但那又是什么环境呢? MFC? ATL? 我认为在窗口被销毁之前不会调用析构函数,因此访问控件为时已晚。我不知道为什么这会与CloseAllDocuments
联系在一起。
if(pItemData != NULL)
- 没必要。 delete
被定义为对空指针的无操作,所有实现都接受它。
您的问题标题“”建议您认为存在竞争条件。没有。只需调用析构函数,对话框(及其所有子窗口)就不再存在,正如答案已经指出的那样。
【参考方案1】:
您似乎无法从析构函数中访问列表控件的功能。我不记得这是否是规则,或者是否由于您的代码中的其他一些奇怪情况而发生。通常,您可能不能这样做。
无论如何,您可能想尝试在列表控件的WM_DESTROY
消息的处理程序中进行清理,而不是列表控件的析构函数。
【讨论】:
好像是这样,我几乎想说我在很久以前也看到过这种行为。但是从技术上讲,当控件是列表控件的析构函数时,它仍然不应该被销毁。 zar 是对的——你的类中的清理覆盖CMyListCtrl::DestroyWindow
,然后在清理完成后调用CListCtrl::DestroyWindow
。您通常不会在 MFC 析构函数中执行任何需要有效窗口的操作,因为 CWnd
对象封装了数据,但并不等同于实际窗口。
我建议你在你要添加的WM_DESTROY
处理函数上放一个断点;然后当它被命中时,创建一个数据断点(在断点窗格上),其条件为listcontrol->m_hWnd
更改。在某个时刻,变量将变为空,执行将在那里暂停。然后,您可以单独执行每个相关步骤,这样您就可以更好地了解整个过程是如何发生的。顺便说一句,如果您“甚至无法通过它”,可能是您没有加载相应的符号。【参考方案2】:
你等得太久了。在析构函数中为时已晚。此时,窗口句柄 (m_hWnd) 不再有效,Windows 已销毁该窗口。此时列表控件中的项目已全部删除。正如其他人所指出的,将您自己的 CMyListCtrl::OnDestroy() 函数和 ON_WM_DESTROY() 宏添加到您的 CMyListCtrl 消息映射中。将清理代码放在 OnDestroy() 函数中。
【讨论】:
试过了,虽然它没有在那里断言,但 GetItemCount() 返回零并且对话框已经消失了,所以看起来列表已经被破坏了。 哦我想起来了,它必须在 WM_DELETEITEM 上删除! 通常情况下,我不会像你那样做。通常,集合存在于控件的生命周期之外。在这种情况下,当我调用 SetItemDataPtr() 时,我正在设置一个索引、指针、迭代器或对集合中不需要由控件清理的项的其他引用。【参考方案3】:我发布了解决问题的正确答案。我们需要在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()
在列表window 上运行,但由于它已经被销毁,因此行为未知。
【讨论】:
以上是关于没有足够的时间让析构函数完成?的主要内容,如果未能解决你的问题,请参考以下文章