以下のプログラムを検討してください。複雑なケースから簡略化されています。Objクラスの仮想デストラクタを削除しない限り、以前に割り当てられたメモリの削除に失敗します。仮想デストラクタが存在する場合にのみ、プログラムの出力からの2つのアドレスが異なる理由がわかりません。
// 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;
}
これは、仮想デストラクタが存在する場合の私の実装でのプログラムの出力です。
割り当てられたメモリアドレスは0x8895008から始まります割り当て解除されるメモリは0x889500cから始まります
RUN FAILED(終了値1)
それが何をすることになっているのか尋ねないでください。私が言ったように、それはアリーナがさまざまなタイプのメモリのインターフェースであるというより複雑なケースから来ています。この例では、メモリはヒープから割り当てられ、割り当てが解除されています。