Consider the program below. It has been simplified from a complex case. It fails on deleting the previous allocated memory, unless I remove the virtual destructor in the Obj class. I don’t understand why the two addresses from the output of the program differ, only if the virtual destructor is present.
// GCC 4.4
#include <iostream>
using namespace std;
class Arena {
public:
void* alloc(size_t s) {
char* p = new char[s];
cout << "Allocated memory address starts at: " << (void*)p << '\n';
return p;
}
void free(void* p) {
cout << "The memory to be deallocated starts at: " << p << '\n';
delete [] static_cast<char*> (p); // the program fails here
}
};
struct Obj {
void* operator new[](size_t s, Arena& a) {
return a.alloc(s);
}
virtual ~Obj() {} // if I remove this everything works as expected
void destroy(size_t n, Arena* a) {
for (size_t i = 0; i < n; i++)
this[n - i - 1].~Obj();
if (a)
a->free(this);
}
};
int main(int argc, char** argv) {
Arena a;
Obj* p = new(a) Obj[5]();
p->destroy(5, &a);
return 0;
}
This is the output of the program in my implementation when the virtual destructor is present:
Allocated memory address starts at: 0x8895008
The memory to be deallocated starts at: 0x889500cRUN FAILED (exit value 1)
Please don’t ask what the program it’s supposed to do. As I said it comes from a more complex case where Arena is an interface for various types of memory. In this example the memory is just allocated and deallocated from the heap.
thisis not the pointer returned by thenewat linechar* p = new char[s];You can see that the sizesthere is bigger than 5Objinstances. The difference (which should besizeof (std::size_t)) is in additional memory, containing the length of the array, 5, immediately before the address contained inthis.OK, the spec makes it clear:
http://sourcery.mentor.com/public/cxx-abi/abi.html#array-cookies
So, the virtual-ness of the destructor is irrelevant, what matters is that the destructor is non-trivial, which you can easily check, by deleting the keyword
virtualin front of the destructor and observe the program crashing.