我已经编写了一个自定义分配器作为概念证明。为了测试它,我使用了std::list
容器。
可悲的是,该程序在列表销毁期间崩溃了(我不是在这里要求查找错误,因为我已经完成了,或者至少我确定已经这样做了。)
我的自定义分配器只是在其构造函数中分配一个大的内存块(使用:: operator new),并将其用作内存分配的池。目的是加速大量小对象的分配。
我的分配器处于裸露的水平:
template<class _Ty>
struct bare_alloc {
// Bare skeleton of my allocator
bare_alloc(size_t _Amount)
: size_{ _Amount }, ptr_{ static_cast<_Ty*>(::operator new(sizeof(_Ty) * _Amount)) }
{ }
bare_alloc(bare_alloc & ref)
: bare_alloc{ ref.size_ }
{ }
// Copy constructor used with rebind
template<class _Oth>
bare_alloc (const bare_alloc<_Oth> & ref)
: size_{ ref.size }, ptr_{ static_cast<_Oth*>(::operator new(sizeof(_Oth) * size_)) }
{ }
~bare_alloc() { /* Memory is automatically released */ }
_Ty * allocate(size_t) { /* return a piece of the block
and register that it has been claimed */ }
void deallocate(_Ty*, size_t) { /* the piece claimed
may now be used again */ }
size_t size_;
std::unique_ptr<_Ty> ptr_;
}
auto* ptr = myAlloc.allocate(10);
无论如何,我设法追查这些问题:
// Visual Studio, file 'list' line 678
void _Alloc_proxy()
{ // construct proxy
typename _Alty::template rebind<_Container_proxy>::other
_Alproxy(_Getal());
/* a call to the copy-constructor acquires resources (memory)*/
_Myproxy() = _Alproxy.allocate(1);
_Alproxy.construct(_Myproxy(), _Container_proxy());
_Myproxy()->_Mycont = &_Get_data();
} /* a call to _Alproxy's dctor releases resources */
// Complementary method to free the list's proxy
void _Free_proxy()
{ // destroy proxy
typename _Alty::template rebind<_Container_proxy>::other
_Alproxy(_Getal());
_Orphan_all();
_Alproxy.destroy(_Myproxy());
_Alproxy.deallocate(_Myproxy(), 1);
_Myproxy() = 0;
}
显然std::list
创建了我的分配器的临时对象,为其代理分配了一个块,然后在该范围的出口处释放了它所在的内存,导致后面描述的崩溃
因此,我的问题是:根据上述事实,我的分配器的最佳设计(即谁应拥有已分配内存的所有权)是什么? (例如,内存可能比分配它的分配器更长)?
编辑:考虑到对该特定问题缺乏兴趣,我决定编辑我的问题并解释我自己的问题解决方案:
首先使用::operator new[]
在出现时分配底层内存 - 我使用了std::allocator::allocate()
一段时间但它使用了::operator new
并且给了我4096字节以上分配的问题 - 然后我存储了std::unique_ptr
中的指针确保正确释放。然后将所有这些安全指针存储在static std::vector
中。由于它是静态的,因此在程序结束或手动释放之前,内存有效。后来,我建立了一个分配器,它使用存储在thread_local static std::vector< _BlockInfo<_Ty> >
中的信息(大小,最后分配的块...)来管理该内存。由于它是静态的(和线程安全的),无论哪个特定实例在其上工作,数据都保持有效,因此这解决了我的问题。
赞赏任何反馈或改进