提高二进制序列化 - 固定长度的误差双阵列 [英] Boost binary serialization - double array of fixed length error
问题描述
我要创建一个存储大量的双打与升压保存/加载的类。负载必须尽可能快,所以得到的二进制格式来工作的目标。
基本上,我有一个存储结构的向量类:
矢量<&DataChunk GT;
在这里DataChunk存储固定长度的双阵列
双数据[2048]
当我使用文本存档(text_iarchive)测试功能,一切都很正常。但是,使用二进制归档的时候,我得到的内存访问违反了反序列化的类。
更奇怪的是,如果我填用相同的双值双阵列(即数据[2048]等于12345的所有元素),它的工作原理。不同的双重价值似乎崩溃了,虽然(见下文)。
下面是我的RAWDATA类:
的#pragma一次
#包括LT&;升压\\序列\\ vector.hpp>
#包括LT&;升压\\序列\\ array.hpp>使用命名空间std;结构DataChunk
{
上市:
双数据[2048]; //这是有问题的区域
INT结束;
私人的:
友元类的boost ::系列化::访问;
模板<类归档和GT;
无效连载(归档和放大器; AR,const的无符号整型版)
{
AR&安培;数据;
AR&安培;结束;
}
};
类RAWDATA
{
私人的:
矢量< DataChunk>块;
友元类的boost ::系列化::访问;
模板<类归档和GT;
无效连载(归档和放大器; AR,const的无符号整型版)
{
AR&安培;块;
}
上市:
无效add_chunk(DataChunk块){chunks.push_back(块);};
矢量< DataChunk> get_chunks(){返回块;};
静态无效保存(RAWDATA路字符串路径);
静态布尔载荷(RAWDATA&安培;第三,串路径);
无效add_raw_data(矢量<&双GT; raw_data);
矢量<&双GT; combine_chunks();
};
我的保存和载入功能,如下所示:
无效RAWDATA ::保存(RAWDATA路路径字符串)
{
的std :: ofstream的文件(路径);
如果(file.good())
{ 提高::档案:: binary_oarchive OA(文件的std :: IOS ::二进制);
//提振::档案:: text_oarchive的OA(文件);
OA<< RD;
}
file.flush();
file.close();
}布尔RAWDATA ::负载(RAWDATA&安培;第三,路径字符串)
{
性病:: ifstream的文件(路径);
如果(file.good())
{ 提高::档案:: binary_iarchive IA(文件的std :: IOS ::二进制);
//提振::档案:: text_iarchive IA(文件);
IA>> RD;
file.close();
返回true;
}
其他
返回false;
}
在我的主要功能,我测试它是这样的:
路径字符串=test.data;
RAWDATA OLD_DATA;
矢量<&双GT;原始数据;
的for(int i = 0; I< 5000;我++)
raw_data.push_back(我* 2048); //更改为恒定值和它的作品...
old_data.add_raw_data(raw_data);//连载
RAWDATA ::保存(OLD_DATA,路径);//反序列化
RAWDATA NEW_DATA;
RAWDATA ::负载(NEW_DATA,路径);//抢块和测试值
矢量< DataChunk> chunks_in = new_data.get_chunks();
的for(int i = 0; I< chunks_in.size();我++)
对于(INT J = 0; J< chunks_in [I] .END; J ++)
COUT&所述;&下; chunks_in [I]的.data [j]的&下;&下;,;
返回0;
您将需要使用
模板<类归档和GT;无效连载(归档和放大器; AR,无符号){
AR&安培;结束;
AR&安培;提高::系列化:: make_array(数据结束);
}
请参阅的http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/wrappers.html#arrays
下面是演示,整装的:
<大骨节病> 住在Coliru 骨节病>
的#include&LT;升压/系列化/ vector.hpp&GT;
#包括LT&;升压/系列化/ array.hpp&GT;结构DataChunk {
上市:
双数据[2048]; //这是有问题的区域
INT结束; 私人的:
友元类的boost ::系列化::访问;
模板&LT;类归档和GT;无效连载(归档和放大器; AR,无符号){
AR&安培;结束;
AR&安培;提高::系列化:: make_array(数据结束);
}
};#包括LT&;升压/ range.hpp&GT;
#包括LT&;升压/范围/ algorithm.hpp&GT;类RAWDATA {
私人的:
的std ::矢量&lt;&DataChunk GT;块;
友元类的boost ::系列化::访问;
模板&LT;类归档和GT;无效连载(归档和放大器; AR,无符号){AR&放大器;大块; } 上市:
无效add_chunk(DataChunk块){chunks.push_back(块); };
的std ::矢量&lt;&DataChunk GT; get_chunks(){返回块; };
静态无效保存(RAWDATA路的std ::字符串路径);
静态布尔载荷(RAWDATA&安培;第三,标准::字符串路径); 无效add_raw_data(性病::矢量&lt;&双GT; raw_data){
DataChunk块;
汽车常量CSIZE =提振::大小(chunk.data); 为size_t N = raw_data.size()
权衡= 0ul; 而(N 0){
汽车N_ =的std ::分(N,CSIZE);
的std :: copy_n(raw_data.begin()+附加赛,N_,chunk.data);
chunk.end = N_;
chunks.push_back(块);
权衡+ = N_;
N - = N_;
}
} 的std ::矢量&lt;&双GT; combine_chunks(){
的std ::矢量&lt;&双GT; - [R;
提高:: for_each的(块,[&安培; R](DataChunk常量和C){性病:: copy_n(c.data,c.end,back_inserter(R));});
返回ř;
}
};#包括LT&;升压/存档/ binary_oarchive.hpp&GT;
#包括LT&;升压/存档/ binary_iarchive.hpp&GT;
#包括LT&;&的fstream GT;无效RAWDATA ::保存(RAWDATA路的std ::字符串路径){
的std :: ofstream的文件(路径);
如果(file.good()){ 提高::档案:: binary_oarchive OA(文件的std :: IOS ::二进制);
//提振::档案:: text_oarchive的OA(文件);
OA&LT;&LT; RD;
}
file.flush();
file.close();
}布尔RAWDATA ::负载(RAWDATA&安培;第三,标准::字符串路径){
性病:: ifstream的文件(路径);
如果(file.good()){ 提高::档案:: binary_iarchive IA(文件的std :: IOS ::二进制);
//提振::档案:: text_iarchive IA(文件);
IA&GT;&GT; RD;
file.close();
返回true;
}其他
返回false;
}#包括LT&;&iostream的GT;RAWDATA产生(){
RAWDATA数据;
的std ::矢量&lt;&双GT;原始数据;
的for(int i = 0; I&LT; 5000;我++)
raw_data.push_back(我* 2048);
data.add_raw_data(raw_data);
返回的数据;
}诠释主(){
标准::字符串常量路径=test.data; {
//连载
RAWDATA常量OLD_DATA =生成();
RAWDATA ::保存(OLD_DATA,路径);
} {
//反序列化
RAWDATA NEW_DATA;
RAWDATA ::负载(NEW_DATA,路径); //抢块和测试值
为(自动D:new_data.combine_chunks())
性病::法院LT&;&LT; D&LT;&LT; ,;
}
}
I'm creating a class that stores lots of doubles for saving/loading with boost. The load needs to be as fast as possible, so getting the binary format to work is the goal.
Basically, I have a class that stores a vector of structs:
vector<DataChunk>
where DataChunk stores a double array of fixed length
double data[2048]
When I test the functionality with using a text archive (text_iarchive), everything works great. However, when using the binary archive, I get memory access violation on deserializing the class.
More bizarrely, if I fill the double array with the same double value (i.e all elements of data[2048] are equal to 12345), it works. Varying double values seems to crash it, though (see below).
Here's my RawData class:
#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();
};
My save and load functions look like this:
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;
}
In my main function, I test it like this:
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;
You will want to use
template <class Archive> void serialize(Archive &ar, unsigned) {
ar & end;
ar & boost::serialization::make_array(data, end);
}
See http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/wrappers.html#arrays
Here is the demo, selfcontained:
#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 << ", ";
}
}
这篇关于提高二进制序列化 - 固定长度的误差双阵列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!