In my scenario I have a DLL with a base class. This DLL can load plugins. Each plugin DLL exports a create function which returns a derived object. I would prefer if the objects from the plugin DLLs could delete themselves.
In the following, I have written down two ways. Please ignore missing public/private statements. The first way is of course simpler because I only need to call delete as usual, but I am not sure whether it works. The second way does an explicit delete this
because this
must have the derived type, right?
// main DLL
class Base1
{
virtual ~Base(){}
};
class Base2
{
virtual ~Base(){}
virtual void destroy() = 0;
};
// plugin DLL without destroy
class Derived1 : public Base1
{
Derived1()
{
m_p = new cSomeClass;
}
virtual ~Derived1()
{
delete m_p;
}
cSomeClass * m_p;
}
// function which is exported
Base1 * createDerived1()
{
return new Derived1;
}
// plugin DLL with destroy
class Derived2 : public Base2
{
Derived2()
{
m_p = new cSomeClass;
}
virtual ~Derived2()
{
delete m_p;
}
virtual void destroy()
{
delete this;
}
cSomeClass * m_p;
}
// function which is exported
Base2 * createDerived2()
{
return new Derived2;
}
int main()
{
Base1 * pBase1 = createDerived1();
delete pBase1;
pBase = nullptr;
// is derived object properly deleted?
Base2 * pBase2 = createDerived2();
pBase2->destroy();
pBase2 = nullptr;
// is derived object properly deleted?
}
Which one does "the right thing", i.e. properly delete the derived object using a base class pointer?
delete
knows the object type and will properly delete it because of the virtual destructor.Base
pointer and does a dynamic cast before delete
. (I have not written an example for this case because I find it unattractive.)The first way seems to be the simplest because it does not require work beside properly writing virtual destructors.
Memory management between DLLs is a real pain.
In general memory allocated in one DLL must not be released in another.
Providing an explicit destroy (delete this
) function, that must be called when the object is no longer needed, is the typical solution.
So go for 2 (write a pure virtual destroy method which is implemented in the derived classes):
class IBase
{
public:
virtual void destroy() = 0;
// Other pure virtual methods.
};
class Derived : public IBase
{
public:
Derived() { m_p = new cSomeClass; }
virtual ~Derived() { delete m_p; }
virtual void destroy() override { delete this; }
private:
cSomeClass *m_p;
};
extern "C" __declspec(dllexport) IBase * __cdecl createDerived()
{
return new Derived;
}
For further details you can read the GREAT Exporting C++ classes from a DLL (from Eli Bendersky's website).