【问题标题】:Bad allocation exception when deserializing std::string from boost::archive:binary_iarchive从 boost::archive:binary_iarchive 反序列化 std::string 时分配错误
【发布时间】:2018-06-14 08:49:01
【问题描述】:

作为一项实验,我正在尝试逐个元素地将std::map<std:string, ValueType> 序列化到二进制文件/从二进制文件序列化。

我正在使用这样的东西:

Live on Wandbox

void Save(const std::string& fname, const MapType& c)
{
    std::ofstream f(fname.c_str(), std::ios::binary);
    boost::archive::binary_oarchive oa(f, boost::archive::no_header);

    oa & c.size();
    for (auto& e : c)
    {
        oa & e.first;
        oa & e.second;
    }
}

void Load(const std::string& fname, MapType& c)
{
    std::ifstream f(fname.c_str(), std::ios::binary);
    boost::archive::binary_iarchive ia(f, boost::archive::no_header);

    int count;
    ia & count;
    for (int i = 0; i < count; ++i)
    {
        std::string key;
        ValueType value;
        ia & key;
        ia & value;
        c[key] = value;
    }
}

顺便说一句:

using ValueType = boost::variant<bool, int, double, std::string>;
using MapType = std::map<std::string, ValueType>;

保存后,我将文件加载回来。 count 被正确读取,但第一个 key 给出了错误的分配异常。

有什么想法吗?

当我将binary_oarchivebinary_iarchive 替换为它们各自的文本等效项时,相同的代码运行良好。

【问题讨论】:

    标签: c++ string serialization boost


    【解决方案1】:

    保存oa &amp; c.size();,然后加载int count;ia &amp; count;:如果size_tint 的大小不同,下一次加载(即第一个ia &amp; key; 调用)将被破坏;然后,我猜std::string 加载程序会读回错误的字符串大小,从而导致bad_alloc 被抛出。

    奇怪的是,由于您的平台(非)幸运字节序和签名表示,计数数据结果只是偶然正确读取...

    在基于文本的情况下,计数数据以文本方式解析,因此序列化继续进行而不会出错。

    顺便说一句,IIRC 标准容器和变体只要参数是自动序列化的,所以你不需要手动编写它们的序列化代码......

    【讨论】:

    • 我本可以看一百万次却看不到它...非常感谢。我知道容器是可序列化的。事实上,我就是这样开始的,而且效果很好。我只是想尝试一下,我最终打算在内存中对其进行序列化,并希望找到最紧凑的格式。我试图查看 std:map 是否以及有多少开销。
    • 关于开销:stackoverflow.com/questions/22459726/… - 一般来说,你不会比库提供的容器序列化做得更好,尤其是在性能方面。 (例如 POD 元素的 std::vector 优化)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    • 2018-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多