C++ 尝试编写自定义分配\u共享分配器并使其成为线程\u本地时崩溃

C++ 尝试编写自定义分配\u共享分配器并使其成为线程\u本地时崩溃,c++,multithreading,c++11,memory,allocator,C++,Multithreading,C++11,Memory,Allocator,我的程序在每个线程中使用make_shared频繁地创建和销毁几种类型的小对象,并且共享的_ptr不会传递给另一个线程,在这种情况下,我决定编写一个自定义的allocate_shared分配器,其成员是boost::pool,以根据类型分配固定大小的内存 我的代码如下: ObjectAllocator.h: #include <boost/pool/pool.hpp> template<typename T> class ObjectAllocator { public

我的程序在每个线程中使用make_shared频繁地创建和销毁几种类型的小对象,并且共享的_ptr不会传递给另一个线程,在这种情况下,我决定编写一个自定义的allocate_shared分配器,其成员是boost::pool,以根据类型分配固定大小的内存

我的代码如下:

ObjectAllocator.h:

#include <boost/pool/pool.hpp>

template<typename T>
class ObjectAllocator
{
public:
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef T value_type;

    auto static constexpr block_size=64+sizeof(value_type);

public:
    ObjectAllocator() noexcept:pool_(block_size){}
    ObjectAllocator(const ObjectAllocator &other) noexcept :pool_(block_size){}
    ~ObjectAllocator()=default;

    template<typename U>
    ObjectAllocator(const ObjectAllocator<U> &other) noexcept :pool_(block_size){}

    template<typename U>
    ObjectAllocator& operator= (const ObjectAllocator<U> &other){
        return *this;
    }

    ObjectAllocator<T>& operator = (const ObjectAllocator &other){
        return *this;
    }

    template<typename U>
    struct rebind{ typedef ObjectAllocator<U> other; };

    T *allocate(size_type n, const void *hint=nullptr){
#ifdef _DEBUG
        assert(n==1);
#endif
        return static_cast<T*>(pool_.malloc());
    }

    void deallocate(T *ptr, size_type n){
#ifdef _DEBUG
        assert(n==1);
#endif
        pool_.free(ptr);
    }

private:
    boost::pool<> ObjectAllocator<T>::pool_(block_size);
}

template<typename T, typename U>
inline bool operator == (const ObjectAllocator<T>&, const ObjectAllocator<U>&){
    return true;
}

template<typename T, typename U>
inline bool operator != (const ObjectAllocator<T>& a, const ObjectAllocator<U> &b){
    return !(a==b);
}


namespace Allocator {
template <typename T>
thread_local ObjectAllocator<T> allocator;
}
#包括
模板
类对象分配器
{
公众:
typedef std::size\u t size\u type;
typedef std::ptrdiff_t difference_type;
typedef T*指针;
typedef const T*const_指针;
typedef T&reference;
类型定义常数T和常数U参考;
类型定义T值_类型;
自动静态constepr块大小=64+sizeof(值类型);
公众:
ObjectAllocator()noexcept:pool_(block_size){
ObjectAllocator(constObjectAllocator&other)无异常:池(块大小){
~ObjectAllocator()=默认值;
模板
ObjectAllocator(constObjectAllocator&other)无异常:池(块大小){
模板
ObjectAllocator和operator=(常量ObjectAllocator和其他){
归还*这个;
}
ObjectAllocator和operator=(常量ObjectAllocator和其他){
归还*这个;
}
模板
结构重新绑定{typedef ObjectAllocator other;};
T*allocate(大小\类型n,常量void*hint=nullptr){
#ifdef_调试
断言(n==1);
#恩迪夫
返回static_cast(pool_u.malloc());
}
无效解除分配(T*ptr,大小\类型n){
#ifdef_调试
断言(n==1);
#恩迪夫
免费游泳池(ptr);
}
私人:
boost::pool ObjectAllocator::pool_u(块大小);
}
模板
内联布尔运算符==(常量对象分配器&,常量对象分配器&){
返回true;
}
模板
内联布尔运算符!=(常量对象分配器&a、常量对象分配器&b){
返回!(a==b);
}
命名空间分配器{
模板
线程\本地对象分配器分配器;
}
main.cpp:

class ObjectA{
public:
    int s=0;
    void func(){
        std::cout<<s<<std::endl;
    }
    ObjectA() {//std::cout<<"()"<<std::endl;}
    ~ObjectA() {//std::cout<<"~"<<std::endl;}
};

std::vector<std::shared_ptr<ObjectA>> vec;
void test(){
    static uint32_t loop_count=1000*1000;
    for(uint32_t i=0;i<loop_count;i++){
         shared_ptr<ObjectA> packet = allocate_shared<ObjectA, ObjectAllocator<ObjectA>>(Allocator::allocator<ObjectA>);
         vec.push_back(packet);
    }
    vec.clear();
}

std::vector<std::shared_ptr<ObjectA>> vec2;
void test2(){
    static uint32_t loop_count=1000*1000;
    for(uint32_t i=0;i<loop_count;i++){
        shared_ptr<ObjectA> packet = allocate_shared<ObjectA, ObjectAllocator<ObjectA>>(Allocator::allocator<ObjectA>);
        vec2.push_back(packet);
    }
    vec2.clear();
}

int main() {
    std::thread thread1(test);
    test2();
    return 0;
}
类ObjectA{
公众:
int s=0;
void func(){

std::cout每次调用
ObjectAllocator
的复制构造函数时,它们都会创建
boost::pool
的新实例

由于
std::allocate_-shared
复制分配器(),用于分配
std::shared_-ptr
ObjectAllocator
实例在
shared_-ptr
被销毁之前会与其池一起被销毁

相关问题:

可能与您的问题无关,但也有一些其他问题:

  • 您没有在
    main
    中加入
    thread1
    。这将调用
    std::terminate
    ,并使程序崩溃
  • boost::pool ObjectAllocator::pool_(block_size);
    -ObjectAllocator::
部分是多余的和非标准的。(afaik仅在MSVC中接受)
您是否尝试过使用调试器单步执行以找出崩溃的地方?@UnholySheep我已经添加了调试信息谢谢您的回复。在阅读了您提到的文档后,我意识到我误解了stl如何使用分配器的一些关键点。我对代码进行了一些小的调整,现在它可以工作了。顺便说一句,ObjectAllocator::在我的gcc编译器中被接受,如果它不是标准的,你能告诉我编写这个的标准方法吗?
template<typename T>
class ObjectAllocator
{
public:
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef T value_type;

    auto static constexpr block_size=64+sizeof(value_type);

public:
    ObjectAllocator() noexcept{}
    ObjectAllocator(const ObjectAllocator &other) noexcept {}
    ~ObjectAllocator()=default;

    template<typename U>
    ObjectAllocator(const ObjectAllocator<U> &other) noexcept {}

    template<typename U>
    ObjectAllocator& operator= (const ObjectAllocator<U> &other){
        return *this;
    }

    ObjectAllocator<T>& operator = (const ObjectAllocator &other){
        return *this;
    }

    template<typename U>
    struct rebind{ typedef ObjectAllocator<U> other; };

    T *allocate(size_type n, const void *hint=nullptr){
#ifdef _DEBUG
        assert(n==1);
#endif
        return static_cast<T*>(pool_.malloc());
    }

    void deallocate(T *ptr, size_type n){
#ifdef _DEBUG
        assert(n==1);
#endif
        pool_.free(ptr);
    }

private:
    thread_local static boost::pool<> pool_;
};

template<typename T>
thread_local boost::pool<> ObjectAllocator<T>::pool_(block_size);


template<typename T, typename U>
inline bool operator == (const ObjectAllocator<T>&, const ObjectAllocator<U>&){
    return true;
}

template<typename T, typename U>
inline bool operator != (const ObjectAllocator<T>& a, const ObjectAllocator<U> &b){
    return !(a==b);
}

namespace Allocator {
template <typename T>
thread_local static ObjectAllocator<T> allocator;
}

template <typename T, typename ...Args>
inline auto custom_make_shared(Args... args){
    return std::allocate_shared<T,ObjectAllocator<T>>(Allocator::allocator<T>,std::forward<Args>(args)...);
}