Discussion:
Boost serialization: Problem reading strings from binary archive
Mahesh Venkitachalam
2007-11-10 13:43:50 UTC
Permalink
Hello,

I am having a strange problem with std::string as I am trying to read
from a binary archive using Boost serialization. I am new to this, and
it is possible that I have not understood the usage. In the code
below, the string "faultblock" seems to be causing the problem. The
code crashes in the ia & tst line which is reading back the archive -
the stack indicates that it is trying to read an invalid string.

I have tried to minimize the code I need to post, but sorry if this is
still too much.

I'd appreciate any help with this. I am using Boost 1.34.0 on windows
XP.

Best Regards

Mahesh

//
// test.cpp
//
#include <iomanip>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <boost/archive/text_iarchive
.hpp>
#include <boost/archive/text_oarchive.hpp
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/list.hpp>

#include "Attribute4dv.h"

using namespace std;

class Test
{
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar.template register_type<AttrDouble4dv>();
ar.template register_type<AttrString4dv>();

ar & _attrs;
}

public:

vector<Attribute4dv*> _attrs;

Test() {}
~Test() {}
};

int main(int argc, char* arv[])
{
// save data to archive
{
Test* tst = new Test;
vector<double> dVals;
dVals.push_back(1.1);
dVals.push_back(2.2);
AttrDouble4dv* attr1 = new AttrDouble4dv;
attr1->_name = "attr1";
attr1->_vals = dVals;
tst->_attrs.push_back(attr1);

vector<string> lut;
lut.push_back("2001");
lut.push_back("2002");
vector<int> lutIndices;
lutIndices.push_back (0);
lutIndices.push_back(1);
AttrString4dv* attr2 = new AttrString4dv;
attr2->_name = "faultblock";
attr2->_indices = lutIndices;
attr2->_lut = lut;
tst->_attrs.push_back(attr2);

const Test* tst2 = tst;
std::ofstream ofs("test.bin");
boost::archive::binary_oarchive oa(ofs);
oa & tst2;
}

// read data from archive
{
Test* tst;
std::ifstream ifs("test.bin", std::ios::binary);
boost::archive::binary_iarchive ia(ifs);
ia & tst;
int j = 0;
}

return 0;
}

//
// Attribute4dv.h
//
#ifndef _ATTRIBUTE4DV_H
#define _ATTRIBUTE4DV_H

#include <vector>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>

// Base class
class Attribute4dv
{
public:

Attribute4dv() {}
virtual ~Attribute4dv() {}

// name of attribute
std::string _name;

private:

// for serialization
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & _name;
}
};

// double attributes
class AttrDouble4dv : public Attribute4dv
{
public:

AttrDouble4dv() {}
~AttrDouble4dv() {}

std::vector<double> _vals;

private:

// for serialization
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
// save/load base class info
ar & boost::serialization::base_object<Attribute4dv>(*this);

ar & _vals;
}
};

// string attributes
class AttrString4dv : public Attribute4dv
{
public:

AttrString4dv() {}
~AttrString4dv() {}

// a lookup table (LUT) of strings
std::vector<std::string> _lut;
// indices to the LUT
std::vector<int> _indices;

private:

// for serialization
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
// save/load base class info
ar & boost::serialization::base_object<Attribute4dv>(*this);

ar & _lut;
ar & _indices;
}
};

#endif // _ATTRIBUTE4DV_H
Robert Ramey
2007-11-10 16:33:58 UTC
Permalink
try replacing
std::ofstream ofs("test.bin");
with
std::ofstream ofs("test.bin", ios::binary);
does that help?

Robert Ramey
"Mahesh Venkitachalam" <***@gmail.com> wrote in message news:***@mail.gmail.com...
Hello,

I am having a strange problem with std::string as I am trying to read
from a binary archive using Boost serialization. I am new to this, and
it is possible that I have not understood the usage. In the code
below, the string "faultblock" seems to be causing the problem. The
code crashes in the ia & tst line which is reading back the archive -
the stack indicates that it is trying to read an invalid string.


I have tried to minimize the code I need to post, but sorry if this is
still too much.


I'd appreciate any help with this. I am using Boost 1.34.0 on windows
XP.


Best Regards


Mahesh


//
// test.cpp
//
#include <iomanip>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <boost/archive/text_iarchive
.hpp>
#include <boost/archive/text_oarchive.hpp
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/list.hpp>


#include "Attribute4dv.h"


using namespace std;


class Test
{
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar.template register_type<AttrDouble4dv>();
ar.template register_type<AttrString4dv>();


ar & _attrs;
}


public:


vector<Attribute4dv*> _attrs;


Test() {}
~Test() {}


};


int main(int argc, char* arv[])
{
// save data to archive
{
Test* tst = new Test;
vector<double> dVals;
dVals.push_back(1.1);
dVals.push_back(2.2);
AttrDouble4dv* attr1 = new AttrDouble4dv;
attr1->_name = "attr1";
attr1->_vals = dVals;
tst->_attrs.push_back(attr1);

vector<string> lut;
lut.push_back("2001");
lut.push_back("2002");
vector<int> lutIndices;
lutIndices.push_back (0);
lutIndices.push_back(1);
AttrString4dv* attr2 = new AttrString4dv;
attr2->_name = "faultblock";
attr2->_indices = lutIndices;
attr2->_lut = lut;
tst->_attrs.push_back(attr2);


const Test* tst2 = tst;
std::ofstream ofs("test.bin");
boost::archive::binary_oarchive oa(ofs);
oa & tst2;
}


// read data from archive
{
Test* tst;
std::ifstream ifs("test.bin", std::ios::binary);
boost::archive::binary_iarchive ia(ifs);
ia & tst;
int j = 0;
}


return 0;


}


//
// Attribute4dv.h
//
#ifndef _ATTRIBUTE4DV_H
#define _ATTRIBUTE4DV_H

#include <vector>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>


// Base class
class Attribute4dv
{
public:


Attribute4dv() {}
virtual ~Attribute4dv() {}


// name of attribute
std::string _name;


private:


// for serialization
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & _name;
}


};


// double attributes
class AttrDouble4dv : public Attribute4dv
{
public:

AttrDouble4dv() {}
~AttrDouble4dv() {}


std::vector<double> _vals;


private:


// for serialization
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
// save/load base class info
ar & boost::serialization::base_object<Attribute4dv>(*this);


ar & _vals;
}


};


// string attributes
class AttrString4dv : public Attribute4dv
{
public:

AttrString4dv() {}
~AttrString4dv() {}


// a lookup table (LUT) of strings
std::vector<std::string> _lut;
// indices to the LUT
std::vector<int> _indices;


private:


// for serialization
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
// save/load base class info
ar & boost::serialization::base_object<Attribute4dv>(*this);


ar & _lut;
ar & _indices;
}


};

#endif // _ATTRIBUTE4DV_H
Mahesh Venkitachalam
2007-11-11 03:01:37 UTC
Permalink
Yes, that was it - thanks very much for looking at it. I was using a text
archive before, and everything was working even after I switched to binary,
till I started using strings. I missed out on adding ios::binary to the
write...

Best Regards

Mahesh
Post by Robert Ramey
try replacing
std::ofstream ofs("test.bin");
with
std::ofstream ofs("test.bin", ios::binary);
does that help?
Robert Ramey
Hello,
I am having a strange problem with std::string as I am trying to read
from a binary archive using Boost serialization. I am new to this, and
it is possible that I have not understood the usage. In the code
below, the string "faultblock" seems to be causing the problem. The
code crashes in the ia & tst line which is reading back the archive -
the stack indicates that it is trying to read an invalid string.
...

Loading...