IDispatch::Invoke(DISPATCH_PROPERTYGET) 是不是会增加返回的 IDispatch 接口上的引用计数?
Posted
技术标签:
【中文标题】IDispatch::Invoke(DISPATCH_PROPERTYGET) 是不是会增加返回的 IDispatch 接口上的引用计数?【英文标题】:Does IDispatch::Invoke(DISPATCH_PROPERTYGET) increment the reference count on the IDispatch interface returned?IDispatch::Invoke(DISPATCH_PROPERTYGET) 是否会增加返回的 IDispatch 接口上的引用计数? 【发布时间】:2013-06-10 00:09:14 【问题描述】:我目前正在开发一个供闭源 VB 使用的 COM 服务器(使用 ATL) 应用。到目前为止一切正常,但我想确保没有泄漏 那里...所以我的问题是:
我是否必须对通过以下方式获得的 IDispatch 指针调用 AddRef 和/或 Release:
VARIANT pVar;
IDispatch->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
&dispparamsNoArgs, &pVar, NULL, NULL);
【问题讨论】:
【参考方案1】:如果您的pVar
拥有一个接口指针(IUnknown*
或IDispatch*
),您已经收到了AddRef
'fed。您有责任在完成后进行匹配的发布,您通常只是间接地清理变体:通过VariantClear
。
该函数通过将 vt 字段设置为 VT_EMPTY 来清除 VARIANTARG。 VARIANTARG 的当前内容首先发布。 [...] 如果 vtfield 是 VT_DISPATCH,则对象被释放。 [...]
顺便说一句,在 ATL 中不需要使用 Invoke 来读取属性。您有随时可用的好帮手:
CComPtr<IDispatch> pDispatch;
CComVariant vFoo;
HRESULT nFooResult = pDispatch.GetPropertyByName(L"Foo", &vFoo);
CComVariant vBar;
HRESULT nBarResult = pDispatch.GetProperty(DISPID_BAR, &vBar);
包装类负责引用管理。
【讨论】:
嗨罗曼!感谢您的回答。我知道可以在我上面提供的精简示例中使用的包装器。不幸的是,我不能使用它们,因为“真实代码”需要通过 DISPARAMS 提供额外的参数,而且我还没有找到可以在这里使用的包装器。【参考方案2】:AddRef() 已在 IDispatch 指针上调用。最常见的是您看不到的代码,例如服务器的 QueryInterface() 方法。顺便说一句,很好地隐藏在 ATL 中。因此接口指针在调用期间不能变为无效,它的引用计数至少为 1。在 Invoke() 调用期间不需要额外的 AddRef/Release 来使其保持活动状态。只需确保在完成后调用 Release()。
接下来,您通常将其留给 ATL 的 CComPtr 或 CComQIPtr 智能指针类,它们会自动生成 AddRef/Release 调用。
如果您正在寻找内存泄漏,那么您将寻找丢失的 Release() 调用。
【讨论】:
亲爱的汉斯!非常感谢。 IDispatch* 是从客户端移交的,所以我不确定它是否已经在我的用例中添加了 AddRef'fed?!以上是关于IDispatch::Invoke(DISPATCH_PROPERTYGET) 是不是会增加返回的 IDispatch 接口上的引用计数?的主要内容,如果未能解决你的问题,请参考以下文章
LPDISPATCH是啥数据类型,他和IDispatch有啥关系