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有啥关系

使用 iDispatch DISPATCH_PROPERTYGET 在 IE 中拒绝权限

SpringMVC总结

GCD 开发

guava eventbus代码分析

iOS -- 单例类