1

Why does my COM Smart Pointer try to delete when I return from func. I would think that it's still in scope. Is there a way to avoid this?

This is the definition in the .TLH file

_COM_SMARTPTR_TYPEDEF(IComItem, __uuidof(IComItem));

static IComItemPtr m_pItem;

LPDISPATCH func()
{
    IComItemPtr  pItem = m_pItem;

    pItem = pItem->GetParent();  // Returns parent as IComItemPtr

    return pItem;   // Gets deleted here

}

2 Answers 2

3

Your function's return type is a raw IDispatch* pointer, not an IComItemPtr object (or at least an IDispatchPtr object). The issue you are seeing is due to you incorrectly mixing a smart pointer with a raw pointer.

Since your function does not return a smart wrapper object, a conversion must be performed to convert pItem to IDispatch*. The only conversion that pItem can perform in this situation is to IComItem*, which the compiler can then implicitly convert to IDispatch* (since IComItem derives from IDispatch, otherwise your code wouldn't compile at all).

IOW, your return statement is effectively doing this logic:

LPDISPATCH func()
{
    IComItemPtr  pItem = m_pItem;

    pItem = pItem->GetParent();  // Returns parent as IComItemPtr

    //return pItem;
    IComItem *pTemp = pItem.operator IComItem*();
    IDispatch *pDisp = (IDispatch*) pTemp;
    return pDisp;

} // <-- pItem is destructed here!

No matter what, pItem itself is always going to go out of scope when the function exits, decrementing the object's refcount if pItem is referencing an object.

So, what is important is that you return a IDispatch* pointer to a valid object that has its refcount incremented so the object is not freed when pItem's destructor decrements its refcount.

Try this instead:

IComItemPtr func()
{
    return m_pItem->GetParent();  // Returns parent as IComItemPtr
}

Or:

IDispatchPtr func()
{
    return m_pItem->GetParent();  // Returns parent as IComItemPtr converted to IDispatchPtr
}

If you absolutely must return a raw IDispatch* pointer, then you have to either:

  • manually increment the refcount before exiting:

    LPDISPATCH func()
    {
        IComItemPtr pItem = m_pItem->GetParent();  // Returns parent as IComItemPtr
        pItem.AddRef();
        return pItem;
    }
    
  • manually detach the pointer from the wrapper:

    LPDISPATCH func()
    {
        IComItemPtr pItem = m_pItem->GetParent();  // Returns parent as IComItemPtr
        return pItem.Detach();
    }
    
Sign up to request clarification or add additional context in comments.

Comments

0

You first assumption is incorrect.

static IComItemPtr m_pItem;

LPDISPATCH func()
{
    IComItemPtr  pItem = m_pItem;

    pItem = pItem->GetParent();

    return pItem;  // not here.

}   // Gets deleted here (this is where scope is closed).

The return will convert pItem from IComItemPtr to LPDISPATCH (IDispatch*) before the destructor is then called. The result of this conversion will be placed in the destination.

Note: how the conversion happens will depend entirely on the exact definition of the types involved.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.