博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

【转】调试ATL组件中的引用计数问题

Posted on 2011-06-15 13:29  leer  阅读(537)  评论(0编辑  收藏  举报

调试ATL组件中的引用计数问题
(hangwire发表于2002-1-16 0:33:22)

    本文假设你熟悉Visual C++、组件对象模型(COM)、以及活动模板库(ATL)。
如果你怀疑自己的组件有引用计数问题,那么最好是找出导致问题的代码,而且最好是从跟踪所有AddRef() 和Release()方法调用开始,仔细检查返回的结果,找出不匹配的AddRef() 和Release()调用。
在这些方法中设置断点也是很有用的,以便程序运行到断点时,你能检查调用堆栈来判断是谁发出调用的。
为了跟踪此调用,必须在组件的类声明中插入以下的函数OuterAddRef()、 OuterRelease()、 InternalAddRef()、InternalRelease()。

class ATL_NO_VTABLE CFoo : 
  public CComObjectRootEx,
  public CComCoClass,
  public IDispatchImpl
{
public:
  [...]
  ULONG OuterAddRef()
  {
    ULONG ulReturn =
      CComObjectRootEx::OuterAddRef();
    ATLTRACE(_T("++++AddRef()  CFoo::%p  refcount = %d\n"),
      this, m_dwRef);
    return ulReturn;
  }

  ULONG OuterRelease()
  {
    ULONG ulReturn =
      CComObjectRootEx::OuterRelease();
    ATLTRACE(_T("~~~~Release() CFoo::%p  refcount = %d\n"),
      this, m_dwRef);
    return ulReturn;
  }

  ULONG InternalAddRef()
  {
    ULONG ulReturn =
      CComObjectRootEx::InternalAddRef();
    ATLTRACE(_T("++++AddRef()  CFoo::%p  refcount = %d\n"),
      this, m_dwRef);
    return ulReturn;
  }

  ULONG InternalRelease()
  {
    ULONG ulReturn =
      CComObjectRootEx::InternalRelease();
    ATLTRACE(_T("~~~~Release() CFoo::%p  refcount = %d\n"),
      this, m_dwRef);
    return ulReturn;
  }
  …
};

这些方法会改写ATL中CComObjectRootEx相应的方法。当你的组件被聚合时,ATL调用这些方法的"外部(outer)"版本,、否则调用"内部(internal)"版本。在DevStudio的调试环境输出窗口中显示如下信息:

++++AddRef()  CFoo::04540600  refcount = 1
++++AddRef()  CFoo::04540600  refcount = 2
~~~~Release() CFoo::04540600  refcount = 1
++++AddRef()  CFoo::04540600  refcount = 2
++++AddRef()  CFoo::04540600  refcount = 3
~~~~Release() CFoo::04540600  refcount = 2
~~~~Release() CFoo::04540600  refcount = 1
~~~~Release() CFoo::04540600  refcount = 0

注意:在类名之后显示的对象"this"指针值可以帮你区分相同的类中不同的对象。