我正在编写一个简单的内存区域分配器,并面临一个异常安全的小问题。这种情况是当您分配一个本身调用分配器的对象时。内存池的目标是一次分配一堆对象,然后在池被销毁时将它们全部删除。
{
MemoryArena m;
std::string* ptr = m.Allocate<std::string>();
// use ptr whatever
// Cleaned up when pool is destroyed
}
但是当它被多次使用时,这变得相当讨厌。如果内部分配被清理,那么它可以在之后使用 - 不错的假设,因为池的定义是在其生命周期结束之前永远不会删除对象。考虑:
struct X {
X(MemoryArena* ptr, std::string*& ref) {
ref = ptr->Allocate<std::string>();
throw std::runtime_error("hai");
}
};
MemoryArena m;
std::string* ptr;
m.Allocate<X>(&m, ptr);
// ptr is invalid- even though it came from the arena
// which hasn't yet been destroyed
但是如果内部分配不清理,外部分配也无法清理,因为内存区域像硬件堆栈一样线性分配它们,所以我泄漏内存。所以要么我通过提前销毁一个对象来违反我的语义,要么我泄漏内存。
有关如何解决此问题的任何建议?