You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 23:18:17