这个智能指针使用有什么问题?

时间:2013-11-15 21:42:45

标签: c++ com smart-pointers

我最近看到了关于智能指针的PowerPoint和他们的陷阱,这张幻灯片有这张幻灯片(几乎没有评论或解释:

在上下文中:特别是_com_ptr_t,用于处理AddRef / Release的COM接口的智能指针,由_COM_SMARTPTR_TYPEDEF宏创建。*

<小时/> 的错:

IObjectPtr spObj;
for (int i(0); i<MAX; i++)
{
    //passed as actual , no release of previous ptr value
    spOtherObj->get_Obj(&spObj);
}

下一张幻灯片声称如果将spObj放在循环范围内就可以了:

<小时/> 从右:

for (int i(0); i<MAX; i++)
{
    IObjectPtr spObj;
    //passed as actual , no release of previous ptr value
    spOtherObj->get_Obj(&spObj);
}

我研究了这个,但仍然无法弄清楚他们在谈论什么 第二个解决的第一个问题是什么?

<小时/> 我猜测,在更全面的背景下,正确/错误的代码看起来像: 虽然我的假设可能是错的

_COM_SMARTPTR_TYPEDEF(ICalendar, __uuidof(ICalendar))

void get_Calendar(ICalendarPtr* pCalendar)
{
    *pCalendar.CreateInstance(__uuidof(Calendar));          
}

void WrongMethod(void)
{
    ICalendarPtr spCalendar;
    for (int i(0); i<MAX; i++)
    {
        //passed as actual , no release of previous ptr value
        get_Calendar(&spCalendar);
    }
}

2 个答案:

答案 0 :(得分:7)

这很可能是指ATL::CComPtr而不是_com_ptr_t

问题是CComPtr::operator&返回包装指针的地址但不释放它,因此假设被包装的接口不是NULL,则在对象被声明出循环时泄漏对象。

实现确认了这一事实,这是直接从ATL标题复制的,包括注释:

//The assert on operator& usually indicates a bug.  If this is really
//what is needed, however, take the address of the p member explicitly.
T** operator&() throw()
{
    ATLASSERT(p==NULL);
    return &p;
}

_com_ptr_t解决了这个问题,一般情况下使用起来比较方便,因此应该首选适用。

答案 1 :(得分:6)

这些是ATL :: CComPtr智能指针(它们非常聪明,顺便说一句)。

该对象类型的operator &返回其中的原始接口指针的地址。因此,第一个循环实际上并不比这样做更好:

IObject* pObj = NULL;
for (int i(0); i<MAX; i++)
{
    spOtherObj->get_Obj(&pObj);
}

每次迭代,都不会释放先前迭代的接口。它只是丢失,泄露,底层coclass的引用计数将被人为地锁定。

通过将智能指针移动到循环的内部,您现在允许智能指针对象的析构函数清理所获取的每个接口, ->Release(),在下一次迭代之前。扩展的代码实际上是这样的:

for (int i(0); i<MAX; i++)
{
    IObject* pObj = NULL;
    spOtherObj->get_Obj(&pObj);
    if (pObj) pObj->Release();
}