一维std::vector的Boost序列化故障求助
问题排查与修复
核心故障原因分析
你的代码触发段错误主要源于以下几个关键问题:
- 非阻塞请求被覆盖丢失:循环中每次调用
irecv都将结果赋值给同一个req对象,前一次的请求会被销毁,导致未完成的MPI通信引用失效,触发内存访问错误。 - 未等待通信完成就退出:
req.test()仅检查请求是否完成,不会阻塞等待所有通信结束,程序直接return会导致MPI通信资源未正确释放,引发段错误。 - 收发对象容器尺寸不匹配:发送端
TobeSend中的Dummy对象包含2个元素的vector,但接收端TobeRecvd的Dummy只有1个元素,反序列化时会尝试写入超出初始容量的内存,触发越界访问。
修复后的代码
#include <iostream> #include <vector> #include <boost/mpi/environment.hpp> #include <boost/mpi/communicator.hpp> #include <boost/serialization/vector.hpp> #include <boost/mpi.hpp> #include <boost/version.hpp> class Dummy { private: std::vector<unsigned int> array; friend class boost::serialization::access; template <class T> inline void serialize(T & ar, const unsigned int /*version*/) { ar & array; } public: Dummy() = default; explicit Dummy(const int nDivs) { array.resize(nDivs); } ~Dummy() = default; }; int main(int argc, char* const argv[]) { boost::mpi::environment env(argc, argv); boost::mpi::communicator world; std::cout << "Using Boost " << BOOST_VERSION / 100000 << "." // major version << BOOST_VERSION / 100 % 1000 << "." // minor version << BOOST_VERSION % 100 // patch level << " (Rank: " << world.rank() << ")" << std::endl; const int tag = 0; const std::size_t size = 10000; const std::vector<int> neighbrs = {0, 1, 2, 3}; // 发送端对象:每个Dummy包含2个元素的vector std::vector<Dummy> TobeSend; TobeSend.reserve(size); for (std::size_t i = 0; i < size; ++i) { TobeSend.emplace_back(2); } // 接收端对象:默认构造,Boost序列化会自动处理vector的大小 std::vector<Dummy> TobeRecvd(size); std::vector<boost::mpi::request> requests; // 发起所有非阻塞发送请求 for (int target : neighbrs) { if (world.rank() != target) { requests.push_back(world.isend(target, tag, TobeSend)); } } // 发起所有非阻塞接收请求 for (int source : neighbrs) { if (world.rank() != source) { requests.push_back(world.irecv(source, tag, TobeRecvd)); } } // 等待所有通信请求完成 boost::mpi::wait_all(requests.begin(), requests.end()); return 0; }
关键修复说明
- 管理所有MPI请求:用
std::vector<boost::mpi::request>存储所有isend和irecv的请求,避免单个请求对象覆盖导致的资源丢失。 - 等待通信完成:调用
boost::mpi::wait_all确保所有非阻塞通信完成后再退出程序,避免未完成的通信引发的资源错误。 - 统一收发对象初始化:接收端
TobeRecvd使用默认构造的Dummy对象,Boost序列化会自动根据发送的数据调整vector的大小,避免初始尺寸不匹配导致的内存越界。 - 优化对象构造:用
emplace_back构造TobeSend,减少不必要的对象拷贝,提升性能并避免潜在的拷贝错误。 - 完善MPI环境初始化:显式传递
argc和argv给boost::mpi::environment,符合MPI标准初始化流程。
编译命令
保持原编译命令不变:
mpic++ -g mpidatatype.cpp -o output -lboost_mpi -lboost_serialization
内容的提问来源于stack exchange,提问作者MA19
相关产品推荐
相关产品推荐

