Virtual destructor CRT

Today I ran into heap corruption caused by various CRT settings (MTd MDd) in my dll and my actual project. What I found strange is that the application only crashed when I installed the destructor in the dll as virtual. Is there an easy explanation for this? I get that I cannot free memory, but not on my heap, but where exactly is the difference when I define the destructor as non-virtual.

Some code to make it a little understandable

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 not } 
+6
source share
3 answers

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 first case, you instructed the compiler to export only two member functions: CTestClass :: CTestClass () and CTestClass :: ~ CTestClass (). But in the latter case, you ask the compiler to also export the virtual function table. This table is required if you have a virtual destructor. So this could be the cause of the crash. When your program tries to call a virtual destructor, it looks for it in the linked table of virtual functions, but it is not initialized correctly, so we do not know where it actually points. If your destructor is not virtual, you do not need a table of virtual functions, and everything works fine.

+2
source

You really haven't posted enough code to be sure. But your example should NOT crash because there is nothing wrong with it:

 int main(int argc, char* argv[]) { // 1. Allocated an instance of this class in *this/exe* heap, not the DLL heap // if the constructor allocates memory it will be allocated from the DLL heap CTestClass *foo = new CTestClass; // 2. Call the destructor, if it calls delete on anything it will be freed from the DLL heap since thats where the destructor is executing from. Finally we free the foo object from *this/exe* heap - no problems at all. delete foo; } 

I suspect that in your real code you should use the delete operator on an object whose new operator was executed in the dll context. And without the virtual keyword, you probably miss the call to the destructor that performs the cross delete context.

0
source

A virtual destructor is needed only when you have an inheritance hierarchy tree. The virtual keyword will ensure that the pointer to the actual object (and not the type of the object) is destroyed by looking for its destructor in Vtable. Since in this example, following the code that you specified, CTestClass is not inherited from any other class, it is in some way a base class and, therefore, does not need a virtual destructor. I assume that perhaps another of the hood implementation rules triggers this, but you should not use virtual ones with base classes. Each time you create a derived object, you also create its base (for polymorphic reason), and the base is always destroyed (the derivative is only destroyed if you create a virtual destructor for it, therefore, placing it in the vlookup (virtual) table.

thanks

0
source

Source: https://habr.com/ru/post/948964/


All Articles