在具有多个自定义堆分配器实例的环境中,
以下陈述是否正确? : -
每个分配的指针都应该封装在一个类型(例如Ptr
)中
那个缓存指针分配给我(Allo*
)的指针,例如
class Ptr={
Allo* alloPtr; //<-- to keep track
public: void delete(){
//call back to something like "a.deallocate()"
}
}
Allo a; //a custom allocator
Ptr<X> x=a.allocate<X>();
x.delete();
我认为我需要这样做才能让delete()
更容易。
如果分配器更复杂,例如内部保留了很多块: -
Ptr
应该跟踪它所在的块,或者
在分配的内容之前必须有一些微小的标志: -
否则,我必须迭代每个块以找到地址 - &gt;表现不佳。
对不起,如果这太新手了,我对自定义分配器很新 这不是作业 - 我正在努力改进我的游戏库。
我读过: -
答案 0 :(得分:1)
有些实现将元数据保存在正在使用的对象附近,但这些系统受到安全性的影响。
如果您可以控制缓冲区溢出或缓冲区欠载,则可以修补分配器元数据的内存,从而导致代码执行而不是分配。
我见过一种实现,它使用完全独立的内存区域来存储数据和元数据。这可以确保可以识别超出和欠载,错误释放。
该系统的缺点是从指针搜索元数据。
这意味着某种形式的容器需要键入内存,并且受到与大多数容器实现相关联的O(ln n)形式的性能的影响,因此在管理方面的性能低于数据的性能。本地
就地元数据
+----------+ +-----------+ +--------------+
| pointer | | vtable | -------> | int free() |
| to chunk | ------------->|meta data | S void*alloc() S
+----------+ +-----------+
|memory |
| |
+----------+
指向块的指针发生在返回的内存之前,之后(或之后)。 如果在指针数组中使用了内存,则内存[-1]是有效内存,但指向元数据。如果从代码外部,我可以说服它在那里写一个值,我已经控制了程序,因为它将寻找我可以控制的vtable
让我再试一次
每个分配的指针都应该封装在一个类型中(例如Ptr) 那个分配给我的人的缓存指针(Allo *),例如
所以特别不一定每个项目都有自己的元数据。
为了跟踪分配,了解使用哪种方案非常重要。在现代编程中,通常对小项目(<10字节)的分配处理不同于大(> 500字节)的项目。可以从数组中的插槽分配小项目,只保留块的元数据。
较大的尺寸不需要相同的膨胀量,因为开销的相对成本会下降。
我希望将小内存块一起批处理,较大的项目具有单独的元数据。
Ptr应该跟踪它所驻留的块,或者 在分配的内容之前必须有一些微小的标志: -
具体来说,需要找到一种方法来找到用于分配的内存分配方案,这可以通过存储带分配的元数据,或者通过分配地址键入一些外部方案来找到记忆(例如)
std::map<void*, MetaData> mMetadataChunk;
注意使用std :: map分配的危险,每个跟踪项目有2个内存分配。
还存在简单的分配方案,将(线程安全的)链接列表添加到特定类,允许为给定对象轻松地重用内存
class FrequentAllocateDestroy {
...
static SomeListType mSpare;
void* operator new ( std::size_t count ) {
// lock
if (mSpare.empty ) {
return ::new( count );
} else {
void * mem = mSpare.top();
mSpare.pop();
return mem;
}
}
void operator delete( void * mem){
// lock
mSpare.push( mem );
}
}