【问题标题】: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);

【问题讨论】:

    标签: c++ com vb6 atl


    【解决方案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?!
    猜你喜欢
    • 2014-08-21
    • 2021-03-23
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 2013-03-30
    • 2011-06-26
    • 2010-11-16
    相关资源
    最近更新 更多