points by dragontamer 4 days ago | 0 comments
In C++, the destructor doesn't call free() because the destructor doesn't know if it's on the stack or heap.
Consider:
void f(){
A* tmp = someFunction(stuff);
foo(tmp);
delete tmp;
}
void g(){
A tmp; // destructor will be called, but no free/delete
}
What is the size of A? Answer: you never know in C++ due to polymorphism. It might be a B or other subclass. It is truly a variable length operation.And secondly, the destructor cannot tell if it's f() or g()
[–] adev_ 4 days ago
[–] dgrunwald 4 days ago
But it's possible for `delete tmp;` to call a user-defined `operator delete()` in the derived class! https://godbolt.org/z/hvePa6jMP
The way this works under the hood is that every polymorphic class has two destructors (so two destructor entries in the vtable): the "complete object destructor" is the ~A() you know from C++, and then there's also the "deleting destructor" which combines ~A() + delete.
So the deleting destructor can call free() while knowing the derived object size, even for a delete-via-base-class-pointer.
[–] cowlevel 3 days ago
At least in the MSVC implementation, "delete tmp;" calls "operator delete" polymorphically, through a hidden virtual function. I think this is because derived classes may override "operator delete"?
You could easily go around it.
The compiler knows when creating the destructor for B.
In your example, to have correct C++, you need to have declared a virtual destruct-or for B. You could encode the size of B in a static offset from the virtual destructor or simply as a return value from it.
This is not how it is done now, mainly because how free was designed in C.
free() design is a terrible mistake. Probably one of the worst design mistake of C with the null terminated / no-length specified string and the preprocessor.