Welcome to MSDN Blogs Sign in | Join | Help

jaredpar's WebLog

Code, rants and ramblings of a programmer.

Syndication

News

Now Reading

Expert F#

What's a better book to read when learning F#?

Essential WPF

Thus far the best book I've read on WPF. Gets right down to working with WPF and the goals/history.

Purely Functional Data Structures

Reading this book makes me feel like I'm back in college. It will really get your mind going and is best read with a whiteboard handy.

Blog Roll

Eric Lippert
Dustin Campbell
Jon Skeet
Coding Horror
Brian McNamara
Brian Bondy
Hub FS
Full List

Gotcha: CComPtrBase<T> assignment

Today what started out as a crash due to a pure virtual call turned into finding a gotcha in CComPtrBase<T>.  Essentially the code in question boiled down to the following.  Can you spot the problem?

void GetAStudent(CComPtrBase<T> &spStudent)
{
    CComPtr<Student> spLocal;
    // Do some operation to get a student
    spLocal = spStudent;
}

The problem isn't apparent until you look at the definition for CComPtrBase<T>::operater =.  See the problem?  Basically CComPtrBase<T>::operator= isn't explicitly defined.  This means that C++ will automatically implement memberwise assignment.  The RHS of the operator= will be a "const CComPtrBase<T>&". 

CComPtr<T> derives from CComPtrBase<T> therefore it satisfies this and a memberwise assignment will occur.  We now have two smart pointers on the same value.  However the second smart pointer, CComPtrBase<T>, did not perform an AddRef.  So when both objects are destroyed there will be an extra Release and hopefully a crash.

The fix?

  1. Use CComPtr<T> or CComPtrEx<T> instead of CComPtrBase<T>
  2. Less Optimal: call AddRef() on spLocal.  

Published Tuesday, April 08, 2008 11:44 AM by Jared Parsons

Filed under: , ,

Comments

# re: Gotcha: CComPtrBase<T> assignment @ Tuesday, April 08, 2008 12:01 PM

3. Use dumb pointers as function parameters:

void GetAStudent(T *pStudent)

Maurits

# re: Gotcha: CComPtrBase<T> assignment @ Tuesday, April 08, 2008 12:20 PM

For a usage case I agree that raw pointers may be an easier solution.  However this is resource aquisition case.  The function is retrieving and returning an instance of Student.  Using a raw pointer provides three ways to fail

1) Caller case pass NULL

2) Caller can use a non-RAII friendly pointer type leading to a possible memory leak

3) Caller may not understand that this is a COM object vs a standard heap object.  Using an std::auto_ptr would compile without errors but would cause a crash (hopefully)

Using a reference parameter of an RAII friendly type prevents all of these bugs from occurring.  Yes it should be the responsibility of the programmer to investigate your API usage.  But isn't it better to prevent the mistake outright?

Jared Parsons

New Comments to this post are disabled
Page view tracker