使用Boost.MPI序列化类中二维数组指针时遇序列化错误求助
问题分析与解决
错误原因
你遇到的error: request for member ‘serialize’ in ‘t’, which is of non-class type ‘int’错误,根源在于:
register_type仅用于多态类类型的序列化,用来识别派生类,对int**这种基本类型指针完全无效,你误用了这个方法。- Boost序列化无法自动处理
int**这种动态分配的二维裸指针——它不知道数组的维度信息,直接序列化指针会导致库尝试将其当作普通对象处理,触发错误。 - 错误地将
Dummy特化为is_mpi_datatype,这个特性只适用于MPI原生支持的数据类型,自定义序列化类型不需要该特化,反而会干扰Boost MPI的序列化流程。
解决方案
要正确序列化动态二维数组,需要手动控制序列化流程:先序列化数组尺寸m_N,再逐行序列化每一个一维数组的元素。同时修复MPI类型特化问题,并补充拷贝构造逻辑避免浅拷贝导致的内存错误。
修改后的完整代码
#include <iostream> #include <set> #include <map> #include <boost/mpi/environment.hpp> #include <boost/mpi/communicator.hpp> #include <boost/mpi.hpp> #include <boost/serialization/array.hpp> #include <algorithm> class Dummy { private: int m_N; int** array; friend class boost::serialization::access; template <class Archive> void serialize(Archive &ar, const unsigned int /*version*/) { ar & m_N; // 逐行序列化一维数组,明确告知数组长度 for (int i = 0; i < m_N + 1; ++i) { ar & boost::serialization::make_array(array[i], m_N + 1); } } // 封装内存分配逻辑 void allocate_memory(int N) { m_N = N; array = new int*[N+1]; for(auto i=0; i < N+1; ++i) { array[i] = new int[N+1]; } } public: Dummy() : m_N(0), array(nullptr) {}; Dummy(const int N) { allocate_memory(N); }; // 拷贝构造函数:避免浅拷贝导致的内存重复释放 Dummy(const Dummy& other) { allocate_memory(other.m_N); for (int i = 0; i < m_N + 1; ++i) { std::copy(other.array[i], other.array[i] + m_N + 1, array[i]); } } // 赋值运算符重载 Dummy& operator=(const Dummy& other) { if (this != &other) { // 释放当前内存 for(auto i=0; i < m_N + 1; ++i) { delete[] array[i]; } delete[] array; // 重新分配内存并拷贝数据 allocate_memory(other.m_N); for (int i = 0; i < m_N + 1; ++i) { std::copy(other.array[i], other.array[i] + m_N + 1, array[i]); } } return *this; } ~Dummy() { if (array != nullptr) { for(auto i=0; i < m_N + 1; ++i) { delete[] array[i]; } delete[] array; } }; }; // 移除错误的is_mpi_datatype特化 int main(int argc, char* const argv[]) { boost::mpi::environment env; boost::mpi::communicator world; std::map<int,std::vector<Dummy>> IdToVecObject; std::vector<Dummy> vec; std::set<int> neigbours; if(world.rank() == 0) { Dummy obj(1); vec.push_back(obj); neigbours.insert(1); IdToVecObject.emplace(1, vec); } if(world.rank() == 1) { Dummy obj(1); vec.push_back(obj); neigbours.insert(0); IdToVecObject.emplace(0, vec); } for(auto& it : IdToVecObject) { int target = it.first; Dummy obj(1); world.send(target, 0, obj); } for(auto i : neigbours) { int source = i ; Dummy obj(1); world.recv(source, 0, obj); } return 0; }
关键修改说明
- 序列化逻辑调整:使用
boost::serialization::make_array明确指定每一行数组的长度,让序列化库正确处理数组内容,而非直接序列化裸指针。 - 移除MPI类型特化:删除
is_mpi_datatype<Dummy>的特化,Boost MPI会自动借助Boost Serialization处理自定义类型。 - 补充拷贝构造与赋值逻辑:避免默认浅拷贝导致的内存重复释放问题,确保对象拷贝时完整复制数组数据。
- 空指针安全处理:析构函数中增加空指针判断,避免非法内存释放。
内容的提问来源于stack exchange,提问作者MA19
相关产品推荐
相关产品推荐

