views:

91

answers:

3

What is the difference between the two lines of code below:

CComPtr< IInterface > m_interface;

IInterface* m_interface;

I know that CComPtr help eliminate memory leaks, but I am getting inconsistent results. When declaring the pointer with CComPtr< IInterface > m_interface; and using the interface in my C# code there are no errors, however using the Interface in VC++ I get an unhandled exception error, even if I comment out the instance creation of IInterface.

I am pretty sure the problem is in here somewhere:

STDMETHODIMP CSomeClass::get_IClass(IClass** var)
{ 
      return m_class_var->QueryInterface(var);
}
STDMETHODIMP CSomeClass::putref_IClass(IClass* var)
{ 
     m_class_var = var;
     return S_OK;
}

When I declare the interface pointer with: IInterface* m_interface; I get a RPC_E_SERVERFAULT error when testing the Interface in C# and have to explicitly call GC.Collect() to avoid the error being thrown after instantiation of a few objects. When testing the Interface in VC++ the error is consistent however when it occurs is different. If I comment out the instance creation of IInterface the code runs fine, however when I try to create an instance I get same error as before, just a vague unhandled exception error. What am I doing wrong here?

A: 

CComPtr< IInterface > m_interface is an object. Whereas IInterface* m_interface is a pointer.

The first will have its destructor called when it goes out of scope and I think (a long time since I used it) it will automatically call m_interface ->Release().

The latter is a pointer to an interface and you have to manage when m_interface->Release() is called.

Can you confirm that the COM object is not being released before access?

Preet Sangha
Thanks. I have edited my question a bit to give more information. I am calling Release() within the VC++ code testing Interface implementation. Its not helping, I suspect I need release/destroy the Object within the unmanaged code even when using CComPtr< IInterface > but I'm not sure.
Reggie McCray
@Reggie: Sometimes you do need to call AddRef/Release on an object, even if it's managed by a CComPtr. You'll need to show us the VC++ code so we can see if you're doing something wrong.
Joe Gauterin
+2  A: 

CComPtr is a smart pointer designed to do the 'right' thing when used with COM idioms.

Your code for get_IClass looks good, but putref_IClass needs to call AddRef on the IClass as you're storing it. If you used CComPtr that would happen automatically.

You'll need to add more details about your VC++ unhandled exception.

Joe Gauterin
I have edited my question a bit to give more information.
Reggie McCray
Thank you. this help understand a bit better. I would vote you up but I don't have enough reputation points
Reggie McCray
+1  A: 

IInstance* m_instance is a simple pointer to an IInstance object. You have to manage the lifetime of this pointer yourself. You don't new and delete COM objects like you would ordinary objects. Instead, the operating system allocates the object when you call the WINAPI function `CoCreateInstance' :

// instantiate the CoClass which implements IInstance...
IInstance* instance = 0;
HRESULT hr = CoCreateInstance(__uuidof(mylibrary::MyCoClass), 0, CLSCTX_INPROC_SERVER, __uuidof(mylib::IInstance), &instance);

:   :

// We're done, so release the object...
instance->Release();
instance = 0;

Each COM object implements reference counting. When the last reference to an object has been Release()ed, the COM object destroys itself.

Using CComPtr<> simplifies how you manage the lifetime of the COM objects. It is a smart pointer similar in nature to std::auto_ptr or Boost's shared_ptr, but it works with COM objects. Typically when using a CComPtr you would call the CreateInstance member function rather than calling the WINAPI function, and you would not explicitly call Release when you are done. Just let the CComPtr go out of scope, and when it's destructor is called it will call Release for you:

void function()
{
  // instantiate the CoClass which implements IMyInterface...
  CComPtr<IInstance> instance;
  instance.CoCreateInstance(__uuidof(mylibrary::MyCoClass));

  :   :

  // We're done, so release the object...
  // dont have to do anything, it will be released when function() exits
}
John Dibling