Re: Derived destructor not being called
stanley_r_eisenberg@raytheon.com wrote:
Hi there,
I've been working on an IDL implementention and I'm having problems
with one of the objects' destructors not being called.
The follow is the structure of my IDL file:
interface IMyBase : IUnknown {
....
}
interface IMyDerived : IMyBase {
....
}
Now for an implementation, there is no implementation of IMyBase since
I meant it to be used as a base. But we do have...
Class CMyDerived : public IMyDerived {
public:
CMyDerived();
~CMyDerived()
}
Now to move onto the problem, elsewhere we have a vector containing
pointers:
vector<IMyDerived*> myVector
And now onto the problem, the following will work with the exception
that it doesn not call the destructor!
// stuff things in the vector
for(int i=0; i<10; i++) {
IMyDerived* pitem = NULL;
hr = CoCreateInstance(CLSID_CStuff,
NULL,
CLSCTX_ALL,
IID_IMyDerived,
(void**)&pitem);
IMyBase* pitem2 = reinterpret_cast<IMyBase*>(pitem);
myVector.push_back(pitem2);
}
// now we want to delete the stuff.....
// I'm hoping that the destructor in CMyDerived will be called
// attempt 1, this doesn't work
IMyBase* d = myVector[0];
delete d; // no luck
delete [] d; // no luck
// attempt 2, still no luck
IMyBase* d = myVector[0];
IMyDerived* d2 = reinterpret_cast<IMyDerived*>(d);
delete d2; // no luck
delete [] d2; // no luck
// since this stuff is in a COM DLL, I even tried using some of the
IUNKNOWN mechanisms
(myVector[0])->Release(); // no luck
((IMyDerived*) myVector[0])->Release(); // no luck
Nothing I do seems to get my derived class' destructor to go off which
it causing a memory leak over time.
Does anyone know how I can fix this problem?
Yes. Implement proper COM objects. You don't delete a COM object by
applying the delete operator to a pointer. Rather, you call Release(), which
deletes the object when there are no more references. You also shouldn't
keep un-addref'd pointers to COM objects in containers, since any other use
of the COM object will delete the object out from under your container when
it calls Release.
Typically Release() is implemented as
void __stdcall Release()
{
ULONG count = ::InterlockedDecrement(&m_cRef);
if (0 == count)
delete this;
}
Since IUnknown is typically implemented by the most-derived class, no
virtual destructor is typically needed.
Instead of storing IMyDerived* in your vector, consider using a smart
pointer class, such as the _com_ptr_t<T> class that the compiler support
library defines (#include <comdef.h> to get access to it), or the CComPtr<T>
class that's provided by ATL. Then the vector destructor will "do the right
thing", calling the destructors on all of your smart pointers, which will
Release the COM objects which will in turn delete themselves if they're no
longer being accessed by anything else.
I was thinking about adding a virtual destructor to the base, but
since the base is only defined via an IDL interface I have no idea
how to do this... or if this would even work... or even on the right
track...
That's the right thing to do if you're not defining COM interfaces. Since
you're using IDL, you are defining COM interfaces (there's also no way to
declare a desctructor in IDL, so you wouldn't get very far along that path).
-cd