// 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; }
Allocated memory address starts at: 0x8895008
The memory to be deallocated starts at: 0x889500cRUN Failed (exit value 1)
请不要问它应该做什么程序.正如我所说,它来自一个更复杂的案例,其中Arena是各种类型内存的接口.在这个例子中,内存只是从堆中分配和释放.
解决方法
好的,规范说清楚了:
http://sourcery.mentor.com/public/cxx-abi/abi.html#array-cookies
2.7 Array Operator new Cookies
When operator new is used to create a new array,a cookie is usually stored to remember the allocated length (number of array elements) so that it can be deallocated correctly.
Specifically:
No cookie is required if the array element type T has a trivial destructor (12.4 [class.dtor]) and the usual (array) deallocation function (3.7.3.2 [basic.stc.dynamic.deallocation]) function does not take two arguments.
因此,析构函数的虚拟性是无关紧要的,重要的是析构函数是非平凡的,您可以通过删除析构函数前面的关键字virtual并观察程序崩溃来轻松检查.