A
Abhishek Padmanabh
I have been trying out boost's serialization library for the past few
days. And I have come across a problem serializing a class that has a
reference member. The code is posted as below:
days. And I have come across a problem serializing a class that has a
reference member. The code is posted as below:
Code:
#include <iostream>
#include <fstream>
#include <string>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
//for name value pairs when doing XML archiving
#include <boost/serialization/nvp.hpp>
class MyClassWithNoDefaultConstructor;
std::ostream& operator<<(std::ostream& os, const
MyClassWithNoDefaultConstructor& object);
//global integer variable... whose reference will be a member of
MyClassWithNoDefaultConstructor
int global_int = 10;
class MyClassWithNoDefaultConstructor
{
public:
MyClassWithNoDefaultConstructor(int i, int& ref_)
: intMember(i), ref(ref_)
{}
private:
int intMember;
int& ref;
template<class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(intMember);
ar & BOOST_SERIALIZATION_NVP(ref);
}
friend class boost::serialization::access;
friend std::ostream& operator<<(std::ostream& os, const
MyClassWithNoDefaultConstructor& object);
};
std::ostream& operator<<(std::ostream& os, const
MyClassWithNoDefaultConstructor& object)
{
os << "\nMyClassWithNoDefaultConstructor contents:\n";
os << "intMember - " << object.intMember << "\n";
os << "ref - " << object.ref << "\n";
return os;
}
namespace boost
{
namespace serialization
{
template<class Archive>
inline void save_construct_data(Archive & ar, const
MyClassWithNoDefaultConstructor* t, const unsigned int file_version)
{
// save data required to construct instance
ar << t->intMember;
ar << &(t->ref);
}
template<class Archive>
inline void load_construct_data(Archive & ar,
MyClassWithNoDefaultConstructor* t, const unsigned int file_version)
{
// retrieve data from archive required to construct new instance
int m;
//int * ptr;
int * ptr = new int();
ar >> m;
ar >> ptr;
::new(t)MyClassWithNoDefaultConstructor(m, *ptr);
}
}
}
void SerializeMyClassWithNoDefaultConstructor(const std::string&
filename)
{
MyClassWithNoDefaultConstructor object(111, global_int);
std::ofstream ofs(filename.c_str());
assert(ofs.good());
boost::archive::xml_oarchive xml_oa(ofs);
xml_oa << BOOST_SERIALIZATION_NVP(object);
}
void DeserializeMyClassWithNoDefaultConstructor(const std::string&
filename)
{
char * buffer = new char[sizeof(MyClassWithNoDefaultConstructor)];
MyClassWithNoDefaultConstructor* ptr =
reinterpret_cast<MyClassWithNoDefaultConstructor*>(buffer);
std::ifstream ifs(filename.c_str());
assert(ifs.good());
std::cout << "inside deserialize()" << std::endl;
boost::archive::xml_iarchive xml_ia(ifs);
std::cout << "xml_iarchive constructed" << std::endl;
xml_ia >> BOOST_SERIALIZATION_NVP(*ptr);
std::cout << "deserialized" << std::endl;
std::cout << *ptr;
ptr->~MyClassWithNoDefaultConstructor();
delete[] buffer;
buffer=NULL; ptr=NULL;
}
int main()
{
const std::string filenameMyClassWithNoDefaultConstructor="/tmp/
testfileMyClassWithNoDefaultConstructor.xml";
try
{
SerializeMyClassWithNoDefaultConstructor(filenameMyClassWithNoDefaultConstructor);
DeserializeMyClassWithNoDefaultConstructor(filenameMyClassWithNoDefaultConstructor);
}
catch(const boost::archive::archive_exception& ex)
{
std::cout << ex.what() << "\n";
}
catch(const std::exception& ex)
{
std::cout << ex.what() << "\n";
}
return 0;
}
It compiles fine with g++ 3.4.6. But fails with a segmentation fault.
I tried fiddling around with it but the best I can do is cause it to
fail with a bus error or a stream error. Here is the documentation
that I am referring to - http://www.boost.org/libs/serialization/doc/index.html.
For reference members, the specific documentation page is -
http://www.boost.org/libs/serializa...html#references
The code works (or atleast it seems to) if you remove the reference
member. That is, I have it working for classes that don't have a
default constructor but what if there are constant or reference
members? The documentation seems to suggest it is possible to handle
them as are non-default constructor classes are, but I am not able to
get it to work.
Am I doing something silly there? Or is there a major gap between my
understanding and what the documentation says? I am using boost 1.32 -
can that be a reason? Can anyone help with the problem?