boost serialization: can't deserialize pointer to abstract base class where derived classes overload load_construct_data

I have some pointers to instances of an abstract base class. Some of the derived classes have no default constructors. I can serialize instances of these derived classes by overloading load_construct_data and save_construct_data, but I always get segmentation faults when I try to serialize the base class pointers. Saving works fine, and loading will correctly load the instances of the derived classes, but it segfaults before initializing the pointers. It doesn't seem to matter whether I overload the load_construct_data and save_construct_data of the base class, or how I register my classes and the base/derived relationship, or whether the pointers are ordinary pointers or boost::shared_ptrs. (The details of the segfault messages vary, but it always segfaults). Does anyone have an example of how to serialize such pointers? Here's a trivial example of what I'm trying to do: class Base { Base() {} public: virtual int Apply()=0 const; protected: friend class boost::serialization::access; template<class Archive> void serialize(Archive &ar, const unsigned int version){ } }; BOOST_ASSUME_ABSTRACT(Base); class D1 { public: D1( int der_input): der_int(der_input){} int Apply() const { return der_int; } protected: const int & der_int; friend class boost::serialization::access; template<class Archive> void serialize(Archive &ar, const unsigned int version){ ar & boost::serialization::base_object<Base>(*this); // or boost::serialization::void_cast_register<D1, Base>( // static_cast<D1 *>(NULL), // static_cast<Base *>(NULL) // ) } }; BOOST_CLASS_EXPORT_GUID(D1, "D1"); class D2 { public: D2( int der_input): der_int(der_input){} int Apply() const { return 2*der_int; } protected: const int der_int; friend class boost::serialization::access; template<class Archive> void serialize(Archive &ar, const unsigned int version){ ar & boost::serialization::base_object<base_class_of_T>(*this); // save/load class member variables } }; BOOST_CLASS_EXPORT_GUID(D1, "D1"); namespace boost { namespace serialization { template<class Archive> inline void save_construct_data( Archive & ar, const D1* t, const unsigned int file_version ){ // save data required to construct instance ar << t->der_int; } template<class Archive> inline void load_construct_data( Archive & ar, D1 * t, const unsigned int file_version ){ // retrieve data from archive required to construct new instance int attribute; ar >> attribute; // invoke inplace constructor to initialize instance of my_class ::new(t)D1(attribute); } template<class Archive> inline void save_construct_data( Archive & ar, const D2* t, const unsigned int file_version ){ // save data required to construct instance ar << t->der_int; } template<class Archive> inline void load_construct_data( Archive & ar, D2 * t, const unsigned int file_version ){ // retrieve data from archive required to construct new instance int attribute; ar >> attribute; // invoke inplace constructor to initialize instance of my_class ::new(t)D2(attribute); } }} main(){ ... ar.template register_type<D1>(); ar.template register_type<D2>(); std::vector<Base *> b; ... ar & b; }

Rebecca Lehman wrote:
Does anyone have an example of how to serialize such pointers?
Here are some observations on your email a) note that the issues related to pointers and non-default constructors or orthogonal so you actually have two separate problems here. b) non-default constuctors. Check out files in the ...../libs/serialization/test directory: test_non_default_ctor and test_non_default_ctor2. Make a small program to test your serialization - don't use pointers just make sure the basic serialization works. c) pointers. The system is designed to permit serialization through an abstract pointer to a base class. However, it does require some care 1) there are two methods - "register" and "export" - you've used both in our example. I recommend using one or the other just to keep from getting too confused. 2) remember if you serialize through a derived pointer you can't de-serialize through the base class. That is, you always have to de-serialize to the exact same type you serialized from. 3) your example shows class D2 { ... }; BOOST_CLASS_EXPORT_GUID(D1, "D1"); // should be D2 !!! check out ...../libs/serialization/test/test_exported.cpp for an example. Robert Ramey

Thanks for your helpful comments. a) note that the issues related to pointers and non-default constructors
or orthogonal so you actually have two separate problems here.
I don't think these issues are orthogonal. I have tested cases where there is a default constructor, and everything works. As soon as I overload load_construct_data, it breaks. The underlying class is deserializing correctly, but the pointer causes a segfault.
b) non-default constuctors. Check out files in the ...../libs/serialization/test directory: test_non_default_ctor and test_non_default_ctor2. Make a small program to test your serialization - don't use pointers just make sure the basic serialization works.
It does. Thanks though.
c) pointers. The system is designed to permit serialization through an abstract pointer to a base class. However, it does require some care
1) there are two methods - "register" and "export" - you've used both in our example. I recommend using one or the other just to keep from getting too confused.
As I said in my email, I tried using one or the other--it doesn't matter which.
2) remember if you serialize through a derived pointer you can't de-serialize through the base class. That is, you always have to de-serialize to the exact same type you serialized from.
True.
3) your example shows class D2 { ... }; BOOST_CLASS_EXPORT_GUID(D1, "D1"); // should be D2 !!! check out ...../libs/serialization/test/test_exported.cpp for an example.
Robert Ramey
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
Rebecca Lehman
-
Robert Ramey