【问题标题】:Boost binary serialization - double array of fixed length errorBoost二进制序列化-固定长度错误的双数组
【发布时间】:2015-04-19 21:13:59
【问题描述】:

我正在创建一个存储大量双打的类,用于通过 boost 保存/加载。加载需要尽可能快,所以让二进制格式工作是目标。

基本上,我有一个存储结构向量的类:

vector<DataChunk>

DataChunk 存储一个固定长度的双精度数组

double data[2048]

当我使用文本存档 (text_iarchive) 测试功能时,一切正常。但是,当使用二进制存档时,我在反序列化类时遇到内存访问冲突。

更奇怪的是,如果我用相同的双精度值填充双精度数组(即 data[2048] 的所有元素都等于 12345),它就可以工作。不过,不同的双精度值似乎会使它崩溃(见下文)。

这是我的 RawData 类:

#pragma once
#include <boost\serialization\vector.hpp>
#include <boost\serialization\array.hpp>

using namespace std;

struct DataChunk
{
public:
    double data[2048]; //THIS IS THE PROBLEM AREA
    int end;
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive& ar, const unsigned int version)
    {
        ar & data;
        ar & end;
    }
};


class RawData
{
private:
    vector<DataChunk> chunks;
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive& ar, const unsigned int version)
    {
        ar & chunks;
    }
public:
    void add_chunk(DataChunk chunk){chunks.push_back(chunk);};
    vector<DataChunk> get_chunks(){return chunks;};
    static void save(RawData rd, string path);
    static bool load(RawData & rd, string path);
    void add_raw_data(vector<double> raw_data);
    vector<double> combine_chunks();
};

我的保存和加载功能如下所示:

void RawData::save(RawData rd, string path)
{
    std::ofstream file(path); 
    if(file.good())
    {

        boost::archive::binary_oarchive oa(file, std::ios::binary);
        //boost::archive::text_oarchive oa(file);
        oa << rd;
    }
    file.flush();
    file.close();
}

bool RawData::load(RawData & rd, string path)
{
    std::ifstream file(path);
    if(file.good())
    {

        boost::archive::binary_iarchive ia(file, std::ios::binary); 
        //boost::archive::text_iarchive ia(file);
        ia >> rd;
        file.close();
        return true;
    }
    else
        return false;
}

在我的主要功能中,我这样测试它:

string path = "test.data";
RawData old_data;
vector<double> raw_data;
for(int i = 0; i < 5000; i++)
    raw_data.push_back(i * 2048); //change this to constant value and it works...
old_data.add_raw_data(raw_data);

//serialize
RawData::save(old_data, path);

//deserialize
RawData new_data;
RawData::load(new_data, path);

//grab the chunks and test the values
vector<DataChunk> chunks_in = new_data.get_chunks();
for(int i = 0; i < chunks_in.size(); i++)
    for(int j = 0; j < chunks_in[i].end; j++)
        cout<<chunks_in[i].data[j]<<", ";
return 0;

【问题讨论】:

  • 似乎RawDatastd::deque&lt;double&gt; 差不多?

标签: c++ arrays serialization boost binary


【解决方案1】:

你会想要使用

template <class Archive> void serialize(Archive &ar, unsigned) {
    ar & end;
    ar & boost::serialization::make_array(data, end);
}

http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/wrappers.html#arrays

这是演示,自包含:

Live On Coliru

#include <boost/serialization/vector.hpp>
#include <boost/serialization/array.hpp>

struct DataChunk {
  public:
    double data[2048]; // THIS IS THE PROBLEM AREA
    int end;

  private:
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, unsigned) {
        ar & end;
        ar & boost::serialization::make_array(data, end);
    }
};

#include <boost/range.hpp>
#include <boost/range/algorithm.hpp>

class RawData {
  private:
    std::vector<DataChunk> chunks;
    friend class boost::serialization::access;
    template <class Archive> void serialize(Archive &ar, unsigned) { ar &chunks; }

  public:
    void add_chunk(DataChunk chunk) { chunks.push_back(chunk); };
    std::vector<DataChunk> get_chunks() { return chunks; };
    static void save(RawData rd, std::string path);
    static bool load(RawData &rd, std::string path);

    void add_raw_data(std::vector<double> raw_data) {
        DataChunk chunk;
        auto const csize = boost::size(chunk.data);

        size_t n    = raw_data.size(), 
               offs = 0ul;

        while (n>0) {
            auto n_ = std::min(n, csize);
            std::copy_n(raw_data.begin() + offs, n_, chunk.data);
            chunk.end = n_;
            chunks.push_back(chunk);
            offs += n_;
            n    -= n_;
        }
    }

    std::vector<double> combine_chunks() {
        std::vector<double> r;
        boost::for_each(chunks, [&r](DataChunk const& c) {std::copy_n(c.data, c.end, back_inserter(r));});
        return r;
    }
};

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <fstream>

void RawData::save(RawData rd, std::string path) {
    std::ofstream file(path);
    if (file.good()) {

        boost::archive::binary_oarchive oa(file, std::ios::binary);
        // boost::archive::text_oarchive oa(file);
        oa << rd;
    }
    file.flush();
    file.close();
}

bool RawData::load(RawData &rd, std::string path) {
    std::ifstream file(path);
    if (file.good()) {

        boost::archive::binary_iarchive ia(file, std::ios::binary);
        // boost::archive::text_iarchive ia(file);
        ia >> rd;
        file.close();
        return true;
    } else
        return false;
}

#include <iostream>

RawData generate() {
    RawData data;
    std::vector<double> raw_data;
    for (int i = 0; i < 5000; i++)
        raw_data.push_back(i * 2048);
    data.add_raw_data(raw_data);
    return data;
}

int main() {
    std::string const path = "test.data";

    {
        // serialize
        RawData const old_data = generate();
        RawData::save(old_data, path);
    }

    {
        // deserialize
        RawData new_data;
        RawData::load(new_data, path);

        // grab the chunks and test the values
        for (auto d : new_data.combine_chunks())
            std::cout << d << ", ";
    }
}

【讨论】:

  • 仍然收到相同的错误(并将数组设置为与以前相同的值可以修复它)。我认为这对您来说效果很好?
  • @godan 安全假设 :) (它甚至活在你自己的鼻子前 :))
  • 啊!我想....但是,我实际上只是将您的代码复制并粘贴到一个新项目中,并且错误仍然存​​在。一定是我——但我想不通。也许明天。
  • @godan 创建 SSCCE、列出编译器和库版本、开关等的时间。
  • 这是我得到这个错误的最简单的例子(我认为)。如果您使用文本存档进行序列化,它可以工作。对于二进制,它不会。我正在使用 MSVC 2012 进行编译。这是代码...link
猜你喜欢
  • 1970-01-01
  • 2014-08-20
  • 1970-01-01
  • 1970-01-01
  • 2011-03-02
  • 2011-03-16
  • 2015-09-17
  • 1970-01-01
  • 2010-10-29
相关资源
最近更新 更多