I am currently studying COM and the following code confused me.
STDMETHODIMP _(ULONG) ComCar::Release()
{
if(--m_refCount==0)
delete this; // how could this "suicide" deletion be possible?
return m_refCount;
}
I am wondering how could it be possible to delete an object instance within its member method? So I made the following experiment:
class A
{
public:
void Suicide(void);
void Echo(void);
char name;
};
void A::Echo(void)
{
::printf("echo = %c\n",name);
}
void A::Suicide(void)
{
delete this;
}
int main(void)
{
A a;
a.name='a';
a.Suicide(); //failed
}
And the execution does failed at a.Suicide(). The debug report some "Debug Assertion Failed". Could someone shed some light on me? Cause I am totally a newbie on COM.
A related thread is here: Question about COM Release() method
In your example,
Suicide()
fails because it's calling delete on an object that hasn't been dynamically allocated, which is invalid whether or not the calling function is a member.Member functions can
delete
this
- if they know thethis
pointer has been dynamically allocated (vianew
). However, they can't access members after that point, so strictly speaking the example you gave:results in undefined behavior at the
return
statement.Change your main's body to:
You can only delete what was built by
new
, of course -- it makes no difference if that delete is in a member function or elsewhere.delete this
is valid only when the object was allocated using the new operator. For COM reference counting, this is not unusual.However, there is another caveat: accessing member variables after
delete this
is undefined, because the memory for the object has already been returned to the free store. The first code sample you posted does this. To fix it, use a local variable:There is a simple reason for this. new and delete must match.
So if you create an object in an dll and handle it to another part (exe, dll) C runtime might be different. In this case you can not call delete because the runtime has no knowlegde about the pointer you want to delete. It might crash.
Because of this its a good design to integrate the suicide method. In Com its a pair of methods.
which means that the pointer has a counter to remember how many owner an object has. Only if the last owner calls delete the object is really deleted.
But I think there is an error in the implementation you posted.
should not be possible when the object is deleted. At least the behavior is undefined. I think you need to store m_refCount on an local variable to return it in delete case.
You cannot delete an object that was not dynamically allocated. COM objects are dynamically allocated.
This works:
Use
new
to allocate new object of class which your going to destroy by callingdelete
.