Boost Serialization Segfault - c++

I am trying to serialize a class member. The following snippet of code will show the relevant class definitions and the non-intrusive serialization code I have included. I am getting a segfault during my saveHashTable() method which tries to serialize the class member shash_table_. Here is a self-contained trimmed version of the code:
#include <map>
#include <string>
#include <vector>
#include <set>
#include <fstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/list.hpp>
using namespace std;
struct ORROctree
{
public:
struct Node
{
public:
struct Data
{
public:
float n_[3], p_[3];
int id_x_, id_y_, id_z_, lin_id_, num_points_;
std::set<Node*> neighbors_;
void *user_data_;
};
public:
Node::Data *data_;
float center_[3], bounds_[6], radius_;
Node *parent_, *children_;
};
protected:
float voxel_size_, bounds_[6];
int tree_levels_;
Node* root_;
std::vector<Node*> full_leaves_;
};
struct ModelLibrary
{
template <typename T, typename REAL = float>
struct NDIMVoxelStructure
{
T *voxels_;
std::vector<int> total_num_of_voxels_i_;
std::vector<int> num_of_voxels_;
long total_num_of_voxels_;
std::vector<REAL> bounds_;
std::vector<REAL> spacing_;
std::vector<REAL> min_center_;
};
typedef std::pair<const ORROctree::Node::Data*, const ORROctree::Node::Data*> Dipole;
struct Base {
Dipole seg1;
Dipole seg2;
};
typedef std::list<Base> bases_list;
typedef std::map <string, bases_list> SerializeHashTableCell;
// MEMBER TO BE SERIALIZED
typedef NDIMVoxelStructure<SerializeHashTableCell> SerializeHashTable;
public:
SerializeHashTable shash_table_;
public:
bool saveHashTable();
bool loadHashTable();
};
// SERIALIZATION METHODS FOR THE TYPES USED TO FORM THE SERIALIZEHASHTABLE
namespace boost {
namespace serialization {
template<class Archive>
inline void serialize(Archive & ar, ModelLibrary::SerializeHashTable & h, const unsigned int version)
{
ar & h.total_num_of_voxels_;
ar & boost::serialization::make_array(h.voxels_, h.total_num_of_voxels_);
ar & h.num_of_voxels_;
ar & h.total_num_of_voxels_i_;
ar & h.bounds_;
ar & h.spacing_;
ar & h.min_center_;
}
template<class Archive>
inline void serialize(Archive & ar, ModelLibrary::Base & b, const unsigned int version)
{
ar & b.seg1;
ar & b.seg2;
}
template<class Archive>
inline void serialize(Archive & ar, ORROctree::Node n, const unsigned int version)
{
ar & n.data_;
ar & n.center_;
ar & n.bounds_;
ar & n.radius_;
ar & n.parent_;
ar & n.children_;
}
template<class Archive>
inline void serialize(Archive & ar, ORROctree::Node::Data d, const unsigned int version)
{
ar & d.id_x_;
ar & d.id_y_;
ar & d.id_z_;
ar & d.neighbors_;
ar & d.lin_id_;
ar & d.num_points_;
ar & d.p_;
}
}
}
bool ModelLibrary::saveHashTable ()
{
std::ofstream ofs("test.txt");
boost::archive::text_oarchive oa(ofs);
oa << shash_table_;
return true;
}
bool
ModelLibrary::loadHashTable ()
{
std::ifstream ifs("test.txt");
boost::archive::text_iarchive ia(ifs);
ia >> shash_table_;
return true;
}
int main()
{
ModelLibrary m;
m.saveHashTable();
}

You just need to initialize the data in your data structures. All primitive types that haven't been explicitely initialized will have indeterminate ("random") values. This includes the pointers, which means you're invoking Undefined Behaviour by dereferencing pointers to random memory locations.
Here's an update with the simplest initialization that could possibly work, and it runs clean under Valgrind. That's a good tool. Use it!
Also, crank up the compiler messages (-Wall -Wextra -pedantic at a minimum for gcc/clang).
Added in various places:
Data() : id_x_(0), id_y_(0), id_z_(0), lin_id_(0), num_points_(0), user_data_(0)
{
std::fill(n_, n_+3, 0);
std::fill(p_, p_+3, 0);
}
Node() : data_(0), radius_(0), parent_(0), children_(0)
{
std::fill(center_, center_+3, 0);
std::fill(bounds_, bounds_+6, 0);
}
ORROctree() : voxel_size_(0), tree_levels_(0), root_(0)
{
std::fill(bounds_, bounds_+6, 0);
}
NDIMVoxelStructure() : voxels_(0), total_num_of_voxels_(0)
{ }
Base() : seg1(0, 0), seg2(0, 0)
{ }
See it Live On Coliru
Update From the comment: the following lines were clearly in error:
inline void serialize(Archive & ar, ORROctree::Node n, const unsigned int version)
inline void serialize(Archive & ar, ORROctree::Node::Data d, const unsigned int version)
And should have read
inline void serialize(Archive & ar, ORROctree::Node& n, const unsigned int version)
inline void serialize(Archive & ar, ORROctree::Node::Data& d, const unsigned int version)

Related

boost serialization of opencv types

I have the following members of a class (v1 & v2) that I need to serialize to file using boost serialization and then read back in at a later stage.
The first one is a vector of a vector of an open cv type Point3f, and the other is a vector of a vector of type opencv Vec6f as can be seen below.
#include this in the class header
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
//private member variables
std::vector< std::vector<cv::Point3f> > v1;
std::vector< std::vector<cv::Vec6f> > v2;
// Allow serialization to access non-public data members.
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & v1;
ar & v2;
}
I have this defined at the top of my header file so that it can understand how to serialize the point3f and Vec6f types. Is this correct way? I can save the data but when I go to read it all back in, it has the right number of array of vectors but each entry has values of 0. What am I doing wrong? I presume it's do do with the serialize functions themselves but not sure.
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive &ar, cv::Point3_<float> pt3, const unsigned int)
{
ar & pt3.x;
ar & pt3.y;
ar & pt3.z;
}
template<class Archive>
void serialize(Archive &ar, cv::Vec<float,6> vec6, const unsigned int)
{
ar & vec6[0];
ar & vec6[1];
ar & vec6[2];
ar & vec6[3];
ar & vec6[4];
ar & vec6[5];
}
}
}
I use this code to write
std::ofstream ofs1("v1test.bin");
boost::archive::binary_oarchive oa1(ofs1);
oa1 << v1;
and I use this code to read
std::ifstream ifs1("v1test.bin");
boost::archive::binary_iarchive ia1(ifs1);
std::vector< std::vector<cv::Point3f> > test;
ia1 >> test; // this contains the right structure but all values are 0
Any help or points in the right direction would be appreciated
I figured it out - stupid mistake - forgot to add a reference to the variables when passing them in - should be this
namespace boost {
namespace serialization {
template<class Archive>
void serialize(Archive &ar, cv::Point3_<float> &pt3, const unsigned int)
{
ar & pt3.x;
ar & pt3.y;
ar & pt3.z;
}
template<class Archive>
void serialize(Archive &ar, cv::Vec<float,6> &vec6, const unsigned int)
{
ar & vec6[0];
ar & vec6[1];
ar & vec6[2];
ar & vec6[3];
ar & vec6[4];
ar & vec6[5];
}
}
}

Boost missing some data during serialization process

In my setup i have vector of OpacityChannel pointer as a member of Container class.
if i create a varible of OpacityChannel and write it to the archive than everything is written as expected.
when i write Container class object and write it to archive than it misses the data for KeyframeFloat class which is a member of OpacityChannel class.
This is my main file if i change the line from ar & cont; to ar & opacityChannel than it writes the data as required.
I am not able to understand why it is missing data when i write Container class.
#include "pch.h"
#include <iostream>
#include<fstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include "Container.h"
#include "KeyframeFloat.h"
#include <boost/serialization/export.hpp>
BOOST_CLASS_EXPORT_GUID(SumOpacity_Channel, "SumOpacity_Channel")
BOOST_CLASS_EXPORT_GUID(SumKeyframeFloat, "SumKeyframeFloat")
int main()
{
const char* fileName = "saved.txt";
std::vector<int> vec;
Container cont;
SumOpacity_Channel opacityChannel;
SumKeyframeFloat key1, key2;
opacityChannel.AddKeyframe(key1);
opacityChannel.AddKeyframe(key2);
cont.AddChannel(&opacityChannel);
SumKeyframeFloat key1_Restored, key2_Restored;
{
// Create an output archive
std::ofstream ofs(fileName);
boost::archive::text_oarchive ar(ofs);
ar & cont; // KeyframeFloat data is not written.
// if i do ar & opacityChannel; than keyframeFloat data is written in archive
}
Container c_Restored ;
SumOpacity_Channel opacityChannel_Restored;
//load data
{
//create an input stream
std::ifstream ifs(fileName);
boost::archive::text_iarchive ar(ifs);
ar & c_Restored ;
}
do
{
std::cout << '\n' << "Press a key to continue...";
} while (std::cin.get() != '\n');
}
This is the container Class
#pragma once
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/split_member.hpp>
#include "SumChannel.h"
#include "SumOpacityChannel.h"
#include <boost/serialization/vector.hpp>
#include <memory>
#include <boost/serialization/export.hpp>
class Container
{
private:
std::vector< SumOpacity_Channel* > Channels;
public:
Container() {} ;
~Container()
{
if(Channels.size() > 0 )
for (int i = 0; i < Channels.size(); i++)
{
delete Channels[i];
}
}
Container(const Container& c)
{
if (Channels.size() > 0)
Channels.clear(); // clear any previous channels
for (int i = 0; i < c.Channels.size(); i++)
{
Channels.push_back(c.Channels[i]->Clone());
}
}
Container& operator=(const Container& c)
{
if (Channels.size() > 0)
Channels.clear(); // clear any previous channels
for (int i = 0; i < c.Channels.size(); i++)
{
Channels.push_back(c.Channels[i]->Clone());
}
return *this;
}
void AddChannel(SumOpacity_Channel* channel)
{
Channels.push_back(channel->Clone());
}
private:
friend class boost::serialization::access;
template <typename Archive>
void save(Archive& ar, const unsigned version) const {
ar & Channels;
}
template <typename Archive>
void load(Archive& ar, const unsigned version) {
ar & Channels;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
};
This is the keyframeFloat class.
#pragma once
#include "KeyframeBase.h"
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/serialization.hpp>
class SumKeyframeFloat
{
private:
float x;
public:
SumKeyframeFloat() { this->x = 0.0; };
SumKeyframeFloat(float xvalue) : x(xvalue) { };
SumKeyframeFloat(const SumKeyframeFloat& key) : x ( key.x) { };
~SumKeyframeFloat() = default;
private:
friend class boost::serialization::access;
template<typename Archive>
void save(Archive& ar, const unsigned int version) const {
std::cout << "writing float keyframe to Archive" << std::endl;
ar & x;
}
template<typename Archive>
void load(Archive& ar, const unsigned int version) {
ar & x;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
};
This is sum Opacity class header and defination
#include <string>
#include "SumChannel.h"
#include <iostream>
#include <vector>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/vector.hpp>
class SumOpacity_Channel
{
private:
std::vector<SumKeyframeFloat> keyframes;
public:
SumOpacity_Channel();
SumOpacity_Channel(const SumOpacity_Channel &opacityChannel);
~SumOpacity_Channel() = default;
SumOpacity_Channel& operator=(const SumOpacity_Channel &posChannel);
void AddKeyframe(SumKeyframeFloat key);
void DeleteKeyframe(SumKeyframeFloat key, int number);
SumOpacity_Channel* Clone() const;
public:
friend class boost::serialization::access;
template<typename Archive>
void save(Archive& ar, const unsigned int version) const {
ar & keyframes;
}
template<typename Archive>
void load(Archive& ar, const unsigned int version) {
ar & keyframes;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
};
////////////////////////////////////////////////
#include "pch.h"
#include "SumOpacityChannel.h"
SumOpacity_Channel::SumOpacity_Channel()
{
}
/////////////////////////////////////////////////////////////////////////////////////////////
SumOpacity_Channel::SumOpacity_Channel(const SumOpacity_Channel &opacityChannel)
{
this->keyframes.clear();
for (auto KeyFrame : keyframes)
{
this->keyframes.push_back(KeyFrame);
}
}
SumOpacity_Channel& SumOpacity_Channel::operator=(const SumOpacity_Channel &opacityChannel)
{
for (auto KeyFrame : keyframes)
{
this->keyframes.push_back(KeyFrame);
}
return *this;
}
void SumOpacity_Channel::AddKeyframe(SumKeyframeFloat key)
{
keyframes.push_back(key);
}
void SumOpacity_Channel::DeleteKeyframe(SumKeyframeFloat key, int number)
{
keyframes.erase(keyframes.begin() + number);
}
SumOpacity_Channel* SumOpacity_Channel::Clone() const
{
return new SumOpacity_Channel(*this);
}
Your channel is empty.
This copy constructor doesn't make any sense:
SumOpacity_Channel::SumOpacity_Channel(const SumOpacity_Channel &opacityChannel)
{
this->keyframes.clear(); // [1]
for (auto KeyFrame : keyframes) // [2]
{
this->keyframes.push_back(KeyFrame);
}
}
in [2] you are iterating over empty vector - it was cleared the line above.
Also why clear is called? It is constructor, so this vector could not be filled ever before. Calling clear makes sense in copy assignment operator, but not here.
So this
cont.AddChannel(&opacityChannel);
with that
void AddChannel(SumOpacity_Channel* channel)
{
Channels.push_back(channel->Clone());
}
SumOpacity_Channel* SumOpacity_Channel::Clone() const
{
return new SumOpacity_Channel(*this);
}
gives empty vector.
auto KeyFrame : keyframes
should be
auto KeyFrame : opacityChannel.keyframes
?

icu::UnicodeString with boost serialize

I am trying to serialize an icu::UnicodeString with the boost serialization library but am having trouble.
The icu::UnicodeString does not have the required serialize function to serialize it. So I tried to create it, but I am not sure how to make these. Example code:
#include <map>
#include <sstream>
#include <fstream>
#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <boost/serialization/map.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
namespace boost {
namespace serialization {
template<class Archive>
inline void save(
Archive & ar,
const icu_55::UnicodeString& str,
const unsigned int /* file_version */
){
}
template<class Archive>
inline void load(
Archive & ar,
icu_55::UnicodeString& str,
const unsigned int /* file_version */
){
}
// split non-intrusive serialization function member into separate
// non intrusive save/load member functions
template<class Archive>
inline void serialize(
Archive & ar,
icu_55::UnicodeString& str,
const unsigned int file_version
){
boost::serialization::split_free(ar, str, file_version);
}
} // serialization
} // namespace boost
int main()
{
std::map<icu::UnicodeString, int> map = {{"asssdasd",2}, {"qwe",1}, {"Zxc",55}};
std::stringstream ss;
boost::archive::text_oarchive oarch(ss);
oarch << map;
std::map<icu::UnicodeString, int> new_map;
boost::archive::text_iarchive iarch(ss);
iarch >> new_map;
std::cout << (map == new_map) << std::endl;
}
Compile with something like g++ -o new new.cpp -std=c++11 -lboost_serialization -licuuc
Currently the "save" and "load" functions are not implemented. I tried doing just the ar & str; statements that are used in the boost manuals, but I am getting a segmentation fault with that that I am also unable to fix.
I've never worked with LibICU directly, so probably someone can review this code.
However, from my experience using Boost Serialization I think this should be helpful:
template <class Archive>
inline void save(Archive &ar, icu_55::UnicodeString const &str, const unsigned int) {
auto sz = str.getCapacity();
auto len = str.length();
auto buf = str.getBuffer();
if (!buf) throw std::invalid_argument("str");
ar & sz & len & boost::serialization::make_array(buf, sz);
}
template <class Archive>
inline void load(Archive &ar, icu_55::UnicodeString &str, const unsigned int)
{
size_t sz, len;
ar & sz & len;
auto buf = str.getBuffer(sz);
if (!buf) throw std::invalid_argument("str");
try {
ar & boost::serialization::make_array(buf, sz);
}
catch(...) {
str.releaseBuffer(len);
throw;
}
str.releaseBuffer(len);
}
It works for the simple test case provided:
#include <fstream>
#include <map>
#include <sstream>
#include <iostream>
#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/map.hpp>
namespace boost { namespace serialization {
template <class Archive>
inline void save(Archive &ar, icu_55::UnicodeString const &str, const unsigned int) {
auto sz = str.getCapacity();
auto len = str.length();
auto buf = str.getBuffer();
if (!buf) throw std::invalid_argument("str");
ar & sz & len & boost::serialization::make_array(buf, sz);
}
template <class Archive>
inline void load(Archive &ar, icu_55::UnicodeString &str, const unsigned int)
{
size_t sz, len;
ar & sz & len;
auto buf = str.getBuffer(sz);
if (!buf) throw std::invalid_argument("str");
try {
ar & boost::serialization::make_array(buf, sz);
}
catch(...) {
str.releaseBuffer(len);
throw;
}
str.releaseBuffer(len);
}
// split non-intrusive serialization function member into separate
// non intrusive save/load member functions
template <class Archive>
inline void serialize(Archive &ar, icu_55::UnicodeString &str, const unsigned int file_version) {
boost::serialization::split_free(ar, str, file_version);
}
} } // serialization // namespace boost
int main() {
std::map<icu::UnicodeString, int> const map = { { "asssdasd", 2 }, { "qwe", 1 }, { "Zxc", 55 } };
std::stringstream ss;
{
boost::archive::text_oarchive oarch(ss);
oarch << map;
}
{
std::map<icu::UnicodeString, int> new_map;
boost::archive::text_iarchive iarch(ss);
iarch >> new_map;
std::cout << (map == new_map) << std::endl;
}
}
Prints
1

How to serialize object with shared_ptr member using boost

There are abstract I1 and derived C1.
There are abstract I2 and derived C2.
I1 have shared_ptr<I2>. How can I make them serializable using boost serializaton? I am attemtping do it, but my application get exception.
#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
struct I1
{
I1() {}
virtual ~I1() = 0 {}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
}
};
struct C1 : I1
{
virtual ~C1() {}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<I1>(*this);
}
};
struct I2
{
virtual ~I2() = 0 {}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & p;
}
boost::shared_ptr<I1> p;
};
struct C2 : I2
{
C2() { p = boost::shared_ptr<I1>(new C1); }
virtual ~C2() { }
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<I2>(*this);
}
};
int main()
{
C2 c2;
std::string s;
std::stringstream ss(s);
boost::archive::binary_oarchive oa(ss);
oa.register_type<I1>();
oa.register_type<C1>();
oa.register_type<I2>();
oa.register_type<C2>();
oa << c2;
boost::archive::binary_iarchive ia(ss);
//ia.register_type<I1>(); // cannot instantiate abstract class
ia.register_type<C1>();
//ia.register_type<I2>(); // cannot instantiate abstract class
ia.register_type<C2>();
ia >> c2;
}
The boost serialization documentation says here interesting things about BOOST_CLASS_EXPORT:
... BOOST_CLASS_EXPORT ...
Hence, the need for export is implied by the usage of a derived class that is manipulated via a pointer or reference to its base class.
Your p pointer does exactly that. Adding these macros to your code also gets rid of the ugly explicit register_type() calls from your main, which is also nice :)
So, this code seems to compile and work in VS2014:
#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>
struct I1
{
I1() {}
virtual ~I1() = 0 {}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
}
};
BOOST_CLASS_EXPORT(I1)
struct C1 : I1
{
virtual ~C1() {}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<I1>(*this);
}
};
BOOST_CLASS_EXPORT(C1)
struct I2
{
virtual ~I2() = 0 {}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & p;
}
boost::shared_ptr<I1> p;
};
BOOST_CLASS_EXPORT(I2)
struct C2 : I2
{
C2() { p = boost::shared_ptr<I1>(new C1); }
virtual ~C2() { }
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<I2>(*this);
}
};
BOOST_CLASS_EXPORT(C2)
int main()
{
C2 c2;
std::string s;
std::stringstream ss(s);
boost::archive::binary_oarchive oa(ss);
oa << c2;
boost::archive::binary_iarchive ia(ss);
ia >> c2;
}
It is interesting, though, that the statement from Boost docs is obviously not true for all compilers, and lots of code examples on the internets just don't work in VS2014.
I think you aren't supposed to register your pure virtual classes on the output archive either.
Alternatively, you can use export. After defining your classes, replace the rest of your code with this:
#include <boost/serialization/export.hpp>
BOOST_CLASS_EXPORT(C1)
BOOST_CLASS_EXPORT(C2)
int main()
{
C2 c2;
std::string s;
std::stringstream ss(s);
{
boost::archive::binary_oarchive oa(ss);
oa << c2;
}
boost::archive::binary_iarchive ia(ss);
ia >> c2;
}
I put the output archive into a separate block. I think it most likely works without it but I want to be sure that everything is flushed (via going out of scope).
Add
BOOST_SERIALIZATION_ASSUME_ABSTRACT(I1)
BOOST_SERIALIZATION_ASSUME_ABSTRACT(I2)
As per the documentation http://www.boost.org/doc/libs/1_39_0/libs/serialization/doc/traits.html#abstract
UPDATE
I've just verified with VS2013RTM and Boost 1_55, it JustWorks(TM), I've
removed the type registrations for abstract bases (they can never be concretely loaded from the archive anyways)
added
#pragma warning(disable: 4244)
#include <boost/config/warning_disable.hpp>
at the top of the file to silence known chatty warnings
Code compiled and runs without error. For good style, you should probably
serialize c2 through a pointer (stack variables can subtly derail object tracking)
Here's the full code I ended up with:
#pragma warning(disable: 4244)
#include <boost/config/warning_disable.hpp>
#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>
struct I1
{
I1() {}
virtual ~I1() = 0 {}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
}
};
struct C1 : I1
{
virtual ~C1() {}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<I1>(*this);
}
};
struct I2
{
virtual ~I2() = 0 {}
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & p;
}
boost::shared_ptr<I1> p;
};
struct C2 : I2
{
C2() { p = boost::shared_ptr<I1>(new C1); }
virtual ~C2() { }
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<I2>(*this);
}
};
int main()
{
boost::shared_ptr<I2> c2(new C2);
std::string s;
std::stringstream ss(s);
boost::archive::text_oarchive oa(ss);
oa.register_type<C1>();
oa.register_type<C2>();
oa << c2;
std::cout << "Serialized form: '" << ss.str() << "'\n";
boost::archive::text_iarchive ia(ss);
ia.register_type<C1>();
ia.register_type<C2>();
ia >> c2;
}
And here's the output:

boost::shared_ptr<Type> does not serialize the data and gives error

Again I have issue while serializing shared pointer using boost and below is code :
//Content.hpp file
#include <boost/serialization/string.hpp>
#include <boost\serialization\shared_ptr.hpp>
#include <boost/serialization/list.hpp>
struct Content
{
std::string type;
boost::shared_ptr<Content> mycontent; // mycontent is of type Content
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & id;
ar & name;
ar & mycontent;
}
public:
Content(void);
Content(const parameter_strings & parms);
~Content(void);
};
// Content.cpp file
Content::Content(void)
{
}
Content::~Content(void)
{
}
Content::Content(const parameter_strings & parms)
{
// implementation part
}
if I comment line " -- boost::shared_ptr mycontent; --" it compiles without error but i need to use shared_ptr and hence it gives error :
it gives error : error C4308: negative integral constant converted to unsigned type
I have included all required header files also but still issue exists.
I already answered this in the comments here:
#user3382670 making the destructor virtual enabled RTTI for your class. This means that typeid(variable) will return the proper runtime type (most derived class) insetad of the statically known type with pointers and references. – sehe Mar 22 at 1:01
Also, since you don't require polymorphism there should be no such problem in the first place: see it Live On Coliru
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/shared_ptr.hpp>
struct Content
{
std::string id, name;
boost::shared_ptr<Content> mycontent;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int /*version*/)
{
ar & id;
ar & name;
ar & mycontent;
}
public:
Content() {}
typedef int parameter_strings;
Content(const parameter_strings & parms) { }
~Content() {}
};
int main()
{
boost::archive::text_oarchive ao(std::cout);
Content x;
ao << x;
}