From examples I've seen COM IUnknown::Release()
function implementation is something like that:
ULONG Release()
{
InterlockedDecrement(&m_count);
if(m_count == 0) {
delete this;
}
return m_count;
}
So, if m_count is 0, so we're deleting "this" object, and returning the ref count. What I don't understand is why it works ?!?!
Deleting the object wouldn't ruin the call stack or is it okay because it is being held by the thread, so it has nothing to do with the object ???
If the object has been deleted, how is it possible that we can return m_count, it should've been deleted. I could have convinced myself that it's okay if after the delete the code would return hard-coded 0, but how come it can return the member ?!?!
Thanks a lot for your help! :-)
What you observe is undefined behavior. The call stack is not changed by
delete this;
anddelete this
by itself is always safe but rendersthis
pointer invalid which means you can't dereference it anymore.There're two possible explanations of what you observe. Either the implementation in question just doesn't dereference
this
pointer to obtainm_count
when returning from the function - it has it loaded onto a register and just uses that value and sothis
is not dereferenced and you don't observe any problem or whendelete
finishes the memory occupied by the object is still mapped into the process address space and remains technically accessible and so dereferencingthis
succeeds andm_count
is read successfully. I suppose the latter is more likely.Whatever the explanation is that undefined behavior, you can't rely on that, use what user Remus Rusanu suggests in his answer.
That code is bogus. One can never trust m_count after the decrement. The correct code is always like this: