ActiveX 插件导致 ASSERT 在 VS2008 中的应用程序退出时失败
Posted
技术标签:
【中文标题】ActiveX 插件导致 ASSERT 在 VS2008 中的应用程序退出时失败【英文标题】:ActiveX plugin causes ASSERT to fail on application exit in VS2008 【发布时间】:2008-10-15 15:52:57 【问题描述】:我使用“ESRI MapObjects LT2”ActiveX 插件的 MFC 应用程序在关闭它时向我抛出了一个 ASSERT。
错误发生在cmdtarg.cpp
:
CCmdTarget::~CCmdTarget()
#ifndef _AFX_NO_OLE_SUPPORT
if (m_xDispatch.m_vtbl != 0)
((COleDispatchImpl*)&m_xDispatch)->Disconnect();
ASSERT(m_dwRef <= 1); //<--- Fails because m_dwRef is 3
#endif
m_pModuleState = NULL;
我使用 VC9 构建了(本机 C++)应用程序。 当我使用 VC6 编译应用程序时,它的表现很好。
这可能是什么原因?
【问题讨论】:
【参考方案1】:这看起来像一个引用计数。这个“目标”是否可以被其他东西引用,而不是释放它?
【讨论】:
天啊!我刚刚注意到问题上的“引用计数器”标签。对不起。 :-( 没问题.. 我尽量让所有相关信息都易于发现;不过在这里没用,我猜...【参考方案2】:您可以跟踪定义 _ATL_DEBUG_INTERFACES
的 Addref 和 Release 调用
来自http://msdn.microsoft.com/en-us/library/sycfy8ec(VS.80).aspx
_ATL_DEBUG_INTERFACES
在包含任何 ATL 头文件之前定义此宏,以将组件接口上的所有 AddRef 和 Release 调用跟踪到输出窗口。
【讨论】:
【参考方案3】:使用_ATL_DEBUG_INTERFACES
没有产生任何额外的输出...
我在stdafx.
h 的第一行定义了它,直接在#pragma once
之后,所以我想这已经足够早了。
也许原因是我使用 ActiveX 控件的方式:
我不会自己打电话给AddRef()
或Release()
。
MapObjects 安装程序附带了包含大量包装类的示例代码,这些类必须由 VC6 或更早版本生成。
我尝试使用 VC9 自己生成包装类,但出现了我无法修复的错误。
我通过让我的一个窗口有一个类型为CMap1
(派生自CWnd
)的成员来使用控件,这是生成的包装类之一。在CMyWnd::OnCreate()
中,我也调用CMap1::Create()
,就这样,我完成了:我可以添加一个图层,控件会显示世界地图。
我几乎不知道引用计数的内容是什么,因为我没有添加或发布任何引用。至少不是故意的……
该控件相当陈旧:.OCX 文件的版本信息中包含 2000 年。 它也不再被官方支持,但我没有任何替代品。
【讨论】:
【参考方案4】:以下为我解决了这个问题: 在包含控件的窗口中,添加一个 OnDestroy() 处理程序:
void CMyWnd::OnDestroy()
// Apparently we have to disconnect the (ActiveX) Map control manually
// with this undocumented method.
COleControlSite* pSite = GetOleControlSite(MY_DIALOG_CONTROL_ID);
if(NULL != pSite)
pSite->ExternalDisconnect();
CWnd::OnDestroy();
【讨论】:
以上是关于ActiveX 插件导致 ASSERT 在 VS2008 中的应用程序退出时失败的主要内容,如果未能解决你的问题,请参考以下文章
在 Microsoft Access 中安装 VLC ActiveX 插件的问题