在Boost Interprocess中存储POD类型连续字节时遇bad_alloc问题求助
我尝试创建一个POD结构体类型,并将该结构体的vector存储在Boost Interprocess共享内存中。此前使用带Boost共享字符串的实现可正常运行:
template <typename T> using Alloc = ipc::allocator<T, ipc::managed_shared_memory::segment_manager>; using String = ipc::basic_string<char, std::char_traits<char>, Alloc<char>>; struct SharedData { template <typename Alloc> SharedData(size_t aSize, std::string_view aStr, Alloc alloc) : sz(aSize), data(aStr, alloc) {} size_t sz; String data; };
为提升vector元素访问的缓存局部性,让data直接位于vector的连续存储中,我将结构体修改为带固定数组的POD类型:
struct SharedData { SharedData(size_t aSize) : sz(aSize) {} size_t sz; char data[MAX_DATA_SIZE]; };
但执行以下代码创建vector时抛出boost::interprocess::bad_alloc异常:
auto shared_vec = segment_.construct<Vector<SharedData>>((const char *) shared_vec_name.c_str())(segment_.get_segment_manager()); for (int i = 0; i < vector_size; i++) (*shared_vec).emplace_back(max_data_size);
异常信息:
terminate called after throwing an instance of 'boost::interprocess::bad_alloc' what(): boost::interprocess::bad_alloc
我需要创建具备缓存局部性的POD类型vector,请问哪里出错了?
以下是可能的问题点及对应解决方法:
共享内存空间不足
修改后的SharedData每个实例的大小为sizeof(size_t) + MAX_DATA_SIZE,如果MAX_DATA_SIZE较大且vector_size不低,总内存需求会远高于之前的版本(原版本中String的实际数据是动态分配在共享内存的其他区域,vector仅存储字符串的控制块)。
解决方法:计算所需总内存(vector_size * sizeof(SharedData)+ vector自身的管理开销),创建managed_shared_memory时指定足够大的空间,例如:ipc::managed_shared_memory segment(ipc::create_only, "MySharedMem", 100 * 1024 * 1024); // 分配100MBvector的分配器类型错误
确保Vector是基于Boost共享内存分配器定义的,而非默认的std::allocator:template <typename T> using Alloc = ipc::allocator<T, ipc::managed_shared_memory::segment_manager>; template <typename T> using Vector = std::vector<T, Alloc<T>>;若使用默认分配器,vector会尝试在进程私有堆上分配内存,而非共享内存,从而触发
bad_alloc。结构体对齐问题
Boost Interprocess的分配器对内存对齐有严格要求,若SharedData的对齐不符合要求,可能导致分配失败。可以显式指定结构体的对齐方式:struct alignas(std::max_align_t) SharedData { SharedData(size_t aSize) : sz(aSize) {} size_t sz; char data[MAX_DATA_SIZE]; };
内容的提问来源于stack exchange,提问作者Akash

