gpt4 book ai didi

c++ - 尝试编写自定义 allocate_shared 分配器并使其成为 thread_local 时崩溃

转载 作者:行者123 更新时间:2023-11-30 04:50:27 24 4
gpt4 key购买 nike

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

我的代码如下:

对象分配器.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;
}

主要.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;
}

当我尝试测试它时,它崩溃了,我不知道为什么。任何人都可以帮助使其正确吗?提前致谢。

调试器说 shared_ptr_base.h 中有段错误

void* _M_get_deleter(const std::type_info& __ti) const noexcept { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }

当我尝试将 boost::pool 设置为静态时,它在单线程中工作正常而在多线程中崩溃调试器说 shared_ptr_base.h 中有段错误

: _M_use_count(1), _M_weak_count(1) { }


更新:我将 boost::pool 设置为静态 thread_local,它现在可以正常工作了

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)...);
}

最佳答案

ObjectAllocator 的复制构造函数创建 boost::pool 的新实例每次他们被调用时。

作为std::allocate_shared复制分配器(cppreference),ObjectAllocator 的实例用于分配 std::shared_ptrshared_ptr 之前被它的池破坏被摧毁。

相关问题:C++ stateful allocator de-allocate issues

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

  • 你不加入thread1main .这将调用 std::terminate让你的程序崩溃。
  • boost::pool<> ObjectAllocator<T>::pool_(block_size); - ObjectAllocator<T>::部分是多余的和不标准的。 (afaik 仅在 MSVC 中接受)

关于c++ - 尝试编写自定义 allocate_shared 分配器并使其成为 thread_local 时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54967489/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com