【问题标题】:If pointer of a COM interface assigned to a CComPtr object do I need to Release the original one?如果 COM 接口的指针分配给 CComPtr 对象,我需要释放原始的吗?
【发布时间】:2015-10-13 18:07:48
【问题描述】:

如果我创建任何 COM 接口的指针,然后将其分配给同一 COM 接口的 CComPtr 对象,是否需要释放原始 COM 指针?

ISomeComInterface* pSomeComInterface = new CSomeComInterfaceImplemented();
CComPtr<ISomeComInterface> cptrSomeComInterface = pSomeComInterface;

// ....
// Do I need to Release original COM Pointer.
pSomeComInterface->Release();

【问题讨论】:

  • 你实现CSomeComInterfaceImplemented了吗?或者知道它的引用计数是如何工作的?这个 ctor 是否创建了一个 COM 引用数量为 1 的非 COM 指针?
  • class CSomeComInterfaceImplemented 实现了从 IUnknown 接口(间接)派生​​的接口 ISomeComInterface。

标签: c++ com atl


【解决方案1】:

是的,你可能需要释放前一个指针;

CComPtr::operator =

此操作 AddRefs 新对象并释放现有对象(如果存在)。

来自MSDNCComPtr 用于管理 COM 对象的生命周期(它将 RAII 惯用语应用于 COM 对象) - 它自己管理引用计数。

但是,您用于创建 COM 对象的技术是不寻常的,它似乎无法执行 AddRef();因此在这种情况下不需要Release()

CComPtr创建COM对象的常用方法是使用CComPtrCoCreateInstance方法。在这种情况下,AddRef()Release() 方法由 CComPtr 管理,不应由您的客户端代码调用。

【讨论】:

    【解决方案2】:

    CComPtr 负责其内部接口指针的引用计数,由类的实例管理。它对其他指针的引用计数没有影响。也就是说,将指针分配给变量后,您可以确定CComPtr 的内部指针是AddRef'ded 和Release'd,但您应该注意原始接口指针变量@ 987654325@你自己并明确地拨打Release

    【讨论】:

      【解决方案3】:

      这取决于 COM 对象构造函数如何初始化引用计数。很可能它将它设置为零,因此您不需要额外的Release() 调用。然后CComPtr 将处理该对象。

      查看 COM 对象如何初始化引用计数以确定。将引用计数设置为零以外的任何值都不是非法的,唯一的要求是一旦将对象指针返回给 COM 客户端,引用计数就设置为 1,并将所有权传递给客户端。严格来说,因为您 new 对象而不是调用 CoCreateInstance() 或调用 COM 对象的方法,所以不能保证任何特定值。

      因此,如果在对象构造函数中将引用计数设置为 1,则以下内容可能是合法的:

      HRESULT ComMethod( Type** result )
      {
          if( result == 0 ) {
              return E_POINTER;
          }
          //refcount set to 1 in constructor,
          //so no AddRef() call
          *result = new Type();
          return S_OK;
      }
      

      【讨论】:

      • 我认为 COM 甚至不需要明确的引用计数,更不用说引用计数为 1。特别是,我认为 COM 可以与非 COM 引用共存,例如shared_ptr。 COM 只要求您不要删除对象,只要 COM 有引用即可;它不需要在最后一个 COM 引用被释放后立即销毁对象。
      • @MSalters 也许,但这意味着您不能确定某些对象已“销毁”并且系统状态会相应更改 - 某些“文件”或“互斥”对象可能会无限长地保持活动状态,即使你已经发布了所有的参考资料。
      • 是的,但这不是 COM 关心的问题,这是应用程序级逻辑。而且我认为无论如何您都不能确定对象会立即在 DCOM(分布式 COM)中被销毁。出于性能原因,DCOM 不会检查另一端是否仍然存在,因此您可能暂时有过时的引用。这对 COM 有效,因为语义防止早期销毁但允许后期销毁。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-21
      • 1970-01-01
      • 2012-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多