I ran into a heap corruption today caused by different CRT settings (MTd MDd) in my dll and my actual project. What I found strange is that the application only crashed when I set the destructor in the dll to be virtual. Is there an easy explanation for that? I get that I can't free memory that's not on my heap, but where exactly is the difference when I define the destructor as non-virtual.
Some Code just to make it a little clearer
The DLL
#pragma once
class CTestClass
{
public:
_declspec(dllexport) CTestClass() {};
_declspec(dllexport) virtual ~CTestClass() {};
};
And my project
int main(int argc, char* argv[])
{
CTestClass *foo = new CTestClass;
delete foo; // Crashes if the destructor is virtual but works if it's not
}
Virtual destructors in C++ are used to avoid memory leaks especially when your class contains unmanaged code, i.e., contains pointers or object handles to files, databases or other external objects. A destructor can be virtual.
Virtual keyword for destructor is necessary when you want different destructors should follow proper order while objects is being deleted through base class pointer.
The destructor is not user-provided (meaning, it is either implicitly declared, or explicitly defined as defaulted on its first declaration) The destructor is not virtual (that is, the base class destructor is not virtual) All direct base classes have trivial destructors.
The answer to your question is often, but not always. If your abstract class forbids clients to call delete on a pointer to it (or if it says so in its documentation), you are free to not declare a virtual destructor. You can forbid clients to call delete on a pointer to it by making its destructor protected.
There is a difference between
class CTestClass
{
public:
_declspec(dllexport) CTestClass() {}
_declspec(dllexport) virtual ~CTestClass() {}
};
and
__declspec(dllexport) class CTestClass
{
public:
CTestClass() {}
virtual ~CTestClass() {}
};
In the former case you instructed a compiler to export only two member functions: CTestClass::CTestClass() and CTestClass::~CTestClass(). But in the latter case you would instruct a compiler to export the table of virtual functions as well. This table is required once you have got a virtual destructor. So it might be the cause of the crash. When your program tries to call virtual destructor, it looks for it in the associated virtual functions table, but it is not initialized properly so we do not know where it really points then. If your destructor is not virtual, then you do not need any virtual function table and everything works just fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With