正确设计std :: list

时间:2016-09-02 17:48:12

标签: c++ allocator

我已经编写了一个自定义分配器作为概念证明。为了测试它,我使用了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> >中的信息(大小,最后分配的块...)来管理该内存。由于它是静态的(和线程安全的),无论哪个特定实例在其上工作,数据都保持有效,因此这解决了我的问题。

赞赏任何反馈或改进

0 个答案:

没有答案