Boost binary_oarchive动态缓冲区序列化失败问题求助
Boost序列化动态vector缓冲区失败问题
我在使用Boost序列化框架时遇到以下问题:
- 使用
text_archive可正常完成序列化与反序列化 - 使用
binary_oarchive搭配静态char缓冲区(array_sink)也能正常工作 - 改用动态分配的vector缓冲区(
back_inserter)时,序列化失败,对应vector为空,反序列化时抛出iostream错误
复现代码
#include <boost/archive/binary_iarchive.hpp> #include <boost/archive/binary_oarchive.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/access.hpp> #include <boost/serialization/shared_ptr.hpp> #include <boost/iostreams/device/array.hpp> #include <boost/iostreams/device/back_inserter.hpp> #include <boost/iostreams/stream.hpp> #include <cassert> #include <iostream> class MyClass { public: MyClass(int myVar) : _myVar(myVar) {} MyClass() {} int _myVar = 0; friend bool operator== (const MyClass& c1, const MyClass& c2) { return c1._myVar == c2._myVar; } private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int/* version*/) { ar & _myVar; } }; int main(int, char**) { std::shared_ptr<MyClass> srcPtr(new MyClass(42)); std::shared_ptr<MyClass> dstPtr; std::cout << "Serialize using stringstream and text archive" << std::endl; std::stringstream oss; boost::archive::text_oarchive toa(oss); toa << srcPtr; std::cout << oss.str() << std::endl; std::stringstream iss(oss.str()); boost::archive::text_iarchive tia(iss); tia >> dstPtr; assert(*srcPtr == *dstPtr); std::cout << "Dest var is: " << dstPtr-> _myVar << std::endl; dstPtr.reset(); std::cout << "Done" << std::endl; //Static buffer and binary std::cout << "Serialize using static buffer and binary archive" << std::endl; char testBuffer[4096]; boost::iostreams::stream<boost::iostreams::array_sink> static_os(testBuffer); boost::archive::binary_oarchive static_oa(static_os); static_oa << srcPtr; std::cout << "Static buffer, buffer size: " << static_os.tellp() << std::endl; boost::iostreams::stream<boost::iostreams::array_source> static_is(testBuffer); boost::archive::binary_iarchive static_ia(static_is); static_ia >> dstPtr; assert(*srcPtr == *dstPtr); std::cout << "Dest var is: " << dstPtr-> _myVar << std::endl; dstPtr.reset(); std::cout << "Done" << std::endl; //Dynamic vector std::cout << "Serialize using dynamic buffer and binary archive" << std::endl; std::vector<char> buffer; boost::iostreams::stream obs(boost::iostreams::back_inserter(buffer)); boost::archive::binary_oarchive oba(obs); oba << srcPtr; std::cout << "BufferSize: " << buffer.size() << std::endl; boost::iostreams::stream<boost::iostreams::array_source> ibs(buffer.data(),buffer.size()); boost::archive::binary_iarchive iba(ibs); iba >> dstPtr; assert(*srcPtr == *dstPtr); std::cout << "Dest var is: " << dstPtr-> _myVar << std::endl; dstPtr.reset(); std::cout << "Done" << std::endl; }
运行输出
Serialize using stringstream and text archive 22 serialization::archive 18 0 1 1 1 0 0 42 Dest var is: 42 Done Serialize using static buffer and binary archive Static buffer, buffer size: 60 Dest var is: 42 Done Serialize using dynamic buffer and binary archive BufferSize: 0 terminate called after throwing an instance of 'boost::wrapexcept<std::ios_base::failure[abi:cxx11]>' what(): no read access: iostream error Aborted (core dumped)
问题原因与修复方法
原因
Boost归档对象内部维护输出缓冲区,序列化的数据不会立即写入back_inserter关联的vector。若未显式触发缓冲区刷新,vector会保持为空,导致后续反序列化失败。
修复
通过局部作用域销毁归档对象,或手动刷新流,确保数据全部写入vector:
修改后的动态vector序列化代码:
//Dynamic vector std::cout << "Serialize using dynamic buffer and binary archive" << std::endl; std::vector<char> buffer; boost::iostreams::stream obs(boost::iostreams::back_inserter(buffer)); { boost::archive::binary_oarchive oba(obs); oba << srcPtr; } // 归档对象析构时自动刷新内部缓冲区 obs.flush(); // 确保流中剩余数据写入vector std::cout << "BufferSize: " << buffer.size() << std::endl; boost::iostreams::stream<boost::iostreams::array_source> ibs(buffer.data(),buffer.size()); boost::archive::binary_iarchive iba(ibs); iba >> dstPtr; assert(*srcPtr == *dstPtr); std::cout << "Dest var is: " << dstPtr-> _myVar << std::endl; dstPtr.reset(); std::cout << "Done" << std::endl;
说明
- 将
binary_oarchive放在局部代码块中,代码块结束时归档对象析构,自动调用flush()将内部缓冲区内容写入下层流。 - 调用
obs.flush()确保流中所有数据被推送到back_inserter,最终写入vector。
修改后,vector可正确获取序列化数据,反序列化正常执行。
内容的提问来源于stack exchange,提问作者ErniBrown
相关产品推荐
相关产品推荐

