none
creating ATL COM object and ATL CComObject RRS feed

  • Question

  • I'm reading on how to create ATL COM object: http://msdn.microsoft.com/en-us/library/9e31say1%28VS.80%29.aspx.

    I follow the above instruction, and was able to create an instance of a COM class (call it class 1)  inside another COM class (call it class 2). yet when I called the Release() method on class 1, then called Release() on class 2. The server .exe doesn't self-destroy, indicating that something hasn't been completely released. Class 2 is create as LOCAL_SERVER in another client. Does anyone know how to properly use CComObject and its caveats ? I follow the exact above instruction, yet I can see that the object is not completely release (comment out the creation of class 1, everything works fine, class 2 .exe self-destruct once called Release() ) .

    Thanks
    Wednesday, May 6, 2009 1:18 AM

Answers

  • If I understand you correctly, the class 2 COM object is a COM executable, and you are indicating that from inside class 2 you are instantiating a COM object called class 1. If that COM object is defined in the same translation unit as class 2, then the generally accepted approach is to use:

    CComObject<Class1>* pMyObj;
    HRESULT hr = CComObject<Class1>::CreateInstance (&pMyObj);
    if (SUCCEEDED(hr))
    {
         pMyObj->AddRef();
         ...
    }

    Note that the call to CComObject<>::CreateInstance() does not perform an automatic AddRef() in the same manner as CoCreateInstance().

    Now it is your responsibility to decide when the class 2 COM object should release the class 1 COM object. Perhaps you want it to be maintained for the lifetime of the class 2 instance. In that case, call pMyObj->Release() in the FinalRelease() method of class 2.

    • Marked as answer by Wesley Yao Tuesday, May 12, 2009 2:18 AM
    Wednesday, May 6, 2009 3:35 AM

All replies

  • Compile in debug mode, then check the return value from release.  If it's not zero, then your reference count is still positive, meaning something or someone else is still holding a ref to the object.  (Or Addref has mistakenly been called one too many times)


    masher
    Wednesday, May 6, 2009 1:58 AM
  • If I understand you correctly, the class 2 COM object is a COM executable, and you are indicating that from inside class 2 you are instantiating a COM object called class 1. If that COM object is defined in the same translation unit as class 2, then the generally accepted approach is to use:

    CComObject<Class1>* pMyObj;
    HRESULT hr = CComObject<Class1>::CreateInstance (&pMyObj);
    if (SUCCEEDED(hr))
    {
         pMyObj->AddRef();
         ...
    }

    Note that the call to CComObject<>::CreateInstance() does not perform an automatic AddRef() in the same manner as CoCreateInstance().

    Now it is your responsibility to decide when the class 2 COM object should release the class 1 COM object. Perhaps you want it to be maintained for the lifetime of the class 2 instance. In that case, call pMyObj->Release() in the FinalRelease() method of class 2.

    • Marked as answer by Wesley Yao Tuesday, May 12, 2009 2:18 AM
    Wednesday, May 6, 2009 3:35 AM
  • I print out the reference count of Release(), and it's 0. Yet the .EXE still persist.
    Wednesday, May 6, 2009 9:41 PM
  • you're correct in describing my system. that's what I did. I controlled the lifetime of class 1 in class 2. When I call Release() on class 1, I check the return value of Release(), it's 0. yet the class 2 COM executable still persist. is there any caveats of CComObject when using it ? Is there an alternative way to create ATL object ?

    Thanks,

    Tri
    Wednesday, May 6, 2009 9:46 PM
  • Then you have a bug. Personally I don't ever trust the value returned by Release(); you should never need to look at it. Try using _ATL_DEBUG_INTERFACES and see if you can spot the problem. You likely have an AddRef()/Release() mismatch. To prove me wrong you will need to post your code.

    Wednesday, May 6, 2009 10:00 PM