tags:

views:

58

answers:

2

I am learning about COM and reading about this code:

    STDMETHODIMP_ (ULONG) ComCar::Release()
{
   if(--m_refCount==0) delete this;
   return m_refCount;
}

My question is, if the m_refCount==0 and the object is deleted, how could the instance member variable *m_refCount* still exist and be returned? Please forgive me if my question is so naive cause I am a totally newbie on COM. Many thanks.

A related thread is here: http://stackoverflow.com/questions/2309276/how-could-a-member-method-delete-the-object

+1  A: 

Are you sure that the function is returning m_refCount?

I believe that accessing member variables or methods after an object has been deleted is undefined according to the standard, and you can never reliably do this.

The only way I think this could work is if the Release() method creates a local variable on the stack with a copy of the reference count, and this is returned via return value optimization.

LeopardSkinPillBoxHat
+6  A: 

Your concern is valid, the ref count should be moved into a local variable before the object is deleted.

STDMETHODIMP_ (ULONG) ComCar::Release()
{
   ULONG refCount = --m_refCount; // not thread safe
   if(refcount==0) delete this;
   return refCount;
}

But even that code is still wrong because it's not thread safe.

you should use code like this instead.

  STDMETHODIMP_ (ULONG) ComCar::Release()
  {
     LONG cRefs = InterlockedDecrement((LONG*)&m_refCount);
     if (0 == cRefs) delete this;
     return (ULONG)max(cRefs, 0);
  }
John Knoeller
thanks John, but i have some uneasy feeling about "deleting an object within ITS member method", how could this be possibe? If the object cease to exist, how could its member method's execution still be carried on? I am wondering if this could only be explained throuth some research about the object's in-memory layout?
smwikipedia
@smwikipedia: The code for the functions exist regardless of whether the instance of the class exists or not. Stack variables exist until you exit the function. So there is no problem with the function continuing to run after the instance we used to call it goes away, just so long as we don't try and touch any _instance_ data after the delete. you can still safely touch statics and stack variables and code.
John Knoeller
I just made an experiment. I wrote a member method with the body like "delet this", and the execution failed. There seemed to be some memory corruption.
smwikipedia
Hi, John, you could see my experiment code here: http://stackoverflow.com/questions/2309276/how-could-a-member-method-delete-the-object
smwikipedia
@smwikipedia: your experiment is calling `delete` on an instance that was never `new`, that will cause memory corruption. Nothing to do with the fact that the call was in a method. you'll get the same result if replace the `suicide` call with `delete a`
John Knoeller