聚合接口过早释放导致“服务器出现意外情况”

前端之家收集整理的这篇文章主要介绍了聚合接口过早释放导致“服务器出现意外情况”前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

要说明这个问题,首先我说下聚合接口的使用,借助ATL我们是这么用的:

//////////////////////////////////////////////////////////////////////////
// 例子

class CExample
// :......
{
BEGIN_COM_MAP(CExample)
//......
//1.在接口映射表中加上要聚合出去的接口,并指定QI时
// 得到的接口指针
COM_INTERFACE_ENTRY_AGGREGATE(IID_IEXAMPLE,m_spUnk);
END_COM_MAP()

//......

DECLARE_GET_CONTROLLING_UNKNOWN()
DECLARE_PROTECT_FINAL_CONSTRUCT()

HRESULTFinalConstruct()
{
HRESULThr
=S_OK;
//2.我们一般是在FinalConstruct里面做聚合接口的创建
hr=CoCreateInstance(CLSID_EXAMPLE,
GetControllingUnknown(),
CLSCTX_ALL,
IID_IUnknown,
(
void**)&m_spUnk);
returnhr;
}


HRESULTFinalRelease()
{
//3.我们一般是在FinalRelease里面做聚合接口的释放
m_spUnk.Release();
}


public:
CComPtr
<IUnknown>m_spUnk;
}
;

// 例子结束
//////////////////////////////////////////////////////////////////////////

2. 我的问题
我们如果都按上面的方法自然不会有错,但是如果我们不想在FinalConstruct中实现呢?
我的做法是和FinalConstruct/FinalRelease对应的写了两个函数Init()/Uninit(),但是使用
后却发现了莫名奇妙的"服务器出现意外情况",在注释掉部分代码后发现,是因为我在不正确
的地方释放了m_spUnk!我是在Uninit()里面进行的m_spUnk.Release();这样为什么会有问题?
问题就出在:接口映射表中有用到了这个m_spUnk,且这个不会加引用计数,如果你在Uninit中
就释放了这个m_spUnk那么在组件要退出时,他也会运行在接口映射表,这时就会出现异常,因
为他所调用的m_spUnk已经在之前Release了。

3.解决
知道问题了就好办了,我就干脆不把m_spUnkRelease放回FinalRelease,当然要判断一下是否为
空,看来写每一行代码都要对他的作用明明白白才可以。

Good luck~

原文链接:https://www.f2er.com/javaschema/288086.html

猜你在找的设计模式相关文章