Search code examples
c++comatl

Do SmartPointers passed as a generic pointer type need to be freed before passing to another function?


I presume Smart Pointers need to be specifically deleted when passed as a generic pointer type that gets assigned a value or a memory or resource leak will occur?

I'll use CComPtr as example. Will This Leak:

CComPtr<ISomeComObj> mycomobj;
SomeOtherComObject1->FunctionToFindComObject(&mycomobj);
SomeOtherComObject2->FunctionToFindComObject(&mycomobj);

If so, I presume the solution is to:

CComPtr<ISomeComObj> mycomobj;
SomeOtherComObject1->FunctionToFindComObject(&mycomobj);
mycomobj=NULL;
SomeOtherComObject2->FunctionToFindComObject(&mycomobj);

Or CString example:

void GetString(char **pstring)
{
  *pstring=new char[123];
  strncpy(*pstring, "Whatever", 122);
}

// this leaks, correct?
CString s;
GetString(&s);
GetString(&s);
    
// this is okay, correct?
CString c;
GetString(&c);
c=NULL;
GetString(&c);

?


Solution

  • It ultimately depends on how the start pointer and the function are written, but in general, with ATL pointers and functions coded as they should be:

    In debug mode:

    CComPtr<ISomeComObj> mycomobj;
    SomeOtherComObject1->FunctionToFindComObject(&mycomobj);
    SomeOtherComObject2->FunctionToFindComObject(&mycomobj); // will throw an ATL assert
    

    Extract from atlcomcli.h:

    ...
    //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;
    }
    ...
    

    In release, you'll have a problem. So what you should do is this:

    CComPtr<ISomeComObj> mycomobj;
    SomeOtherComObject1->FunctionToFindComObject(&mycomobj);
    mycomobj.Release();
    SomeOtherComObject2->FunctionToFindComObject(&mycomobj);
    

    Note it's good to know CComPtr::Release() can be called safely (in debug and release mode) even if the contained pointer is null, so this works fine for example:

    CComPtr<ISomeComObj> mycomobj;
    mycomobj.Release();
    

    PS: my advice is always use debug mode to develop.