Boost Serialization of shared_ptr

Hi folks Currently I’m having quite some trouble with the boost serialization library. Take the following classes as given: ProtocolFactory.h: #ifndef PROTOCOLFACTORY_H_ #define PROTOCOLFACTORY_H_ #include <boost/serialization/access.hpp> #include <boost/serialization/is_abstract.hpp> #include <boost/shared_ptr.hpp> class Meter; typedef boost::shared_ptr<Meter> MeterPtr; class MeteringProtocol; typedef boost::shared_ptr<MeteringProtocol> MeteringProtocolPtr; class ProtocolFactory { public: ProtocolFactory(); virtual ~ProtocolFactory(); virtual MeteringProtocolPtr getNewProtocolInstance(Meter *const) const = 0; virtual MeteringProtocolPtr getNewProtocolInstance(const MeterPtr &) const = 0; private: friend class boost::serialization::access; template<class archive> void serialize(archive &, const unsigned int) { } }; BOOST_IS_ABSTRACT(ProtocolFactory); typedef boost::shared_ptr<ProtocolFactory> ProtocolFactoryPtr; #endif /*PROTOCOLFACTORY_H_*/ ProtocolFactory.cpp #include "ProtocolFactory.h" ProtocolFactory::ProtocolFactory() { } ProtocolFactory::~ProtocolFactory() { } Iec1107OverSerialFactory.h #ifndef IEC1107OVERSERIALFACTORY_H_ #define IEC1107OVERSERIALFACTORY_H_ #include "ProtocolFactory.h" class Iec1107OverSerialFactory : public ProtocolFactory { public: Iec1107OverSerialFactory(); virtual ~Iec1107OverSerialFactory(); virtual MeteringProtocolPtr getNewProtocolInstance(Meter *const) const; virtual MeteringProtocolPtr getNewProtocolInstance(const MeterPtr &) const; private: friend class boost::serialization::access; template<class archive> void serialize(archive &, const unsigned int); }; #include "Iec1107OverSerialFactory.inc" typedef boost::shared_ptr<Iec1107OverSerialFactory> Iec1107OverSerialFactoryPtr; #endif /*IEC1107OVERSERIALFACTORY_H_*/ Iec1107OverSerialFactory.inc: #include <boost/serialization/base_object.hpp> #include <boost/serialization/export.hpp> #include <boost/serialization/nvp.hpp> BOOST_CLASS_EXPORT(Iec1107OverSerialFactory) // Boost must include Serialization info for this class even if its not directly referencd (e.g. by its base class) template<class Archive> void Iec1107OverSerialFactory::serialize(Archive &ar, const unsigned int version) { using boost::serialization::make_nvp; ar & make_nvp("ProtocolFactory", boost::serialization::base_object<ProtocolFactory>(*this)); } Iec1107OverSerialFactory.cpp: #include "Iec1107OverSerialFactory.h" #include "Iec1107OverSerial.h" #include "../Meter.h" #include "MeteringProtocol.h" using namespace boost; Iec1107OverSerialFactory::Iec1107OverSerialFactory() { } Iec1107OverSerialFactory::~Iec1107OverSerialFactory() { } MeteringProtocolPtr Iec1107OverSerialFactory::getNewProtocolInstance( Meter *const target) const { return MeteringProtocolPtr(new Iec1107OverSerial(target)); } MeteringProtocolPtr Iec1107OverSerialFactory::getNewProtocolInstance( const MeterPtr &target) const { return MeteringProtocolPtr(new Iec1107OverSerial(target)); } MeteringProtocolCompoisteFactory.h #ifndef METERINGPROTOCOLCOMPOSITEFACTORY_H_ #define METERINGPROTOCOLCOMPOSITEFACTORY_H_ #include "ProtocolFactory.h" #include <vector> class MeteringProtocolCompositeFactory : public ProtocolFactory { public: MeteringProtocolCompositeFactory(const std::vector<ProtocolFactoryPtr> &); virtual ~MeteringProtocolCompositeFactory(); virtual MeteringProtocolPtr getNewProtocolInstance(Meter *const) const; virtual MeteringProtocolPtr getNewProtocolInstance(const MeterPtr &) const; const std::vector<ProtocolFactoryPtr> &getFactories() const; private: std::vector<ProtocolFactoryPtr> factories; friend class boost::serialization::access; template<class archive> void serialize(archive &, const unsigned int); }; #include "MeteringProtocolCompositeFactory.inc" typedef boost::shared_ptr<MeteringProtocolCompositeFactory> MeteringProtocolCompositeFactoryPtr; #endif /*METERINGPROTOCOLCOMPOSITEFACTORY_H_*/ MeteringProtocolCompoisteFactory.inc #include <boost/serialization/base_object.hpp> #include <boost/serialization/export.hpp> #include <boost/serialization/vector.hpp> #include <boost/serialization/nvp.hpp> BOOST_CLASS_EXPORT(MeteringProtocolCompositeFactory) // Boost must include Serialization info for this class even if its not directly referencd (e.g. by its base class) namespace boost { namespace serialization { template<class Archive> inline void save_construct_data(Archive &ar, const MeteringProtocolCompositeFactory *pf, const unsigned int version) { using boost::serialization::make_nvp; ar & make_nvp("IncludedProtocols", pf->getFactories()); } template<class Archive> inline void load_construct_data(Archive &ar, MeteringProtocolCompositeFactory *pf, const unsigned int version) { using boost::serialization::make_nvp; std::vector<ProtocolFactoryPtr> factories; ar & make_nvp("IncludedProtocols", factories); ::new(pf)MeteringProtocolCompositeFactory(factories); } } } template<class Archive> void MeteringProtocolCompositeFactory::serialize(Archive &ar, const unsigned int version) { using boost::serialization::make_nvp; ar & make_nvp("ProtocolFactory", boost::serialization::base_object<ProtocolFactory>(*this)); } MeteringProtocolCompositeFactory.cpp: #include "MeteringProtocolCompositeFactory.h" #include "MeteringProtocolComposite.h" #include <iterator> using namespace std; MeteringProtocolCompositeFactory::MeteringProtocolCompositeFactory( const vector<ProtocolFactoryPtr> &factories) : factories(factories) { } MeteringProtocolCompositeFactory::~MeteringProtocolCompositeFactory() { } MeteringProtocolPtr MeteringProtocolCompositeFactory::getNewProtocolInstance( Meter *const target) const { vector<MeteringProtocolPtr> protocols; for (vector<ProtocolFactoryPtr>::const_iterator it = factories.begin(); it != factories.end(); ++it) { protocols.push_back((*it)->getNewProtocolInstance(target)); } return MeteringProtocolPtr(new MeteringProtocolComposite(protocols)); } MeteringProtocolPtr MeteringProtocolCompositeFactory::getNewProtocolInstance( const MeterPtr &target) const { vector<MeteringProtocolPtr> protocols; for (vector<ProtocolFactoryPtr>::const_iterator it = factories.begin(); it != factories.end(); ++it) { protocols.push_back((*it)->getNewProtocolInstance(target)); } return MeteringProtocolPtr(new MeteringProtocolComposite(protocols)); } const std::vector<ProtocolFactoryPtr> &MeteringProtocolCompositeFactory::getFactories() const { return factories; } MeterType.h: #ifndef METERTYPE_H_ #define METERTYPE_H_ #include <boost/serialization/access.hpp> #include <boost/shared_ptr.hpp> #include <string> #include <vector> class ProtocolFactory; typedef boost::shared_ptr<ProtocolFactory> ProtocolFactoryPtr; class MeterType { public: MeterType(const std::string &, const std::vector<std::string> &, const ProtocolFactoryPtr &); virtual ~MeterType(); const std::string &getTypeName() const; const std::vector<std::string> &getRequestedDataItems() const; const ProtocolFactoryPtr &getSupportedProtocols() const; private: MeterType(); std::string typeName; std::vector<std::string> requestedDataItems; // include Data IDs like 1.8.1, standardized for all metering protocls (I hope :) // TODO: Create ProtocolFactoryComposite, including a serialization // TODO: Serialize supportedProtcols and add to constructor ProtocolFactoryPtr supportedProtocols; friend class boost::serialization::access; template<class archive> void serialize(archive &, const unsigned int); }; #include "MeterType.inc" typedef boost::shared_ptr<MeterType> MeterTypePtr; #endif /*METERTYPE_H_*/ MeterType.inc: #include <boost/serialization/nvp.hpp> #include <boost/serialization/shared_ptr.hpp> #include <boost/serialization/string.hpp> #include <boost/serialization/vector.hpp> #include <iostream> namespace boost { namespace serialization { template<class Archive> inline void save_construct_data(Archive &ar, const MeterType *t, const unsigned int version) { using boost::serialization::make_nvp; ar & make_nvp("TypeName", t->getTypeName()); ar & make_nvp("RequestedDataItems", t->getRequestedDataItems()); ar & make_nvp("SupportedProtocols", t->getSupportedProtocols()); } template<class Archive> inline void load_construct_data(Archive &ar, MeterType *t, const unsigned int version) { using boost::serialization::make_nvp; std::string typeName; std::vector<std::string> requestedDataItems; ProtocolFactoryPtr supportedProtocols; ar & make_nvp("TypeName", typeName); ar & make_nvp("RequestedDataItems", requestedDataItems); ar & make_nvp("SupportedProtocols", supportedProtocols); ::new(t)MeterType(typeName, requestedDataItems, supportedProtocols); } } } template<class Archive> void MeterType::serialize(Archive &ar, const unsigned int version) { } MeterType.cpp: #include "MeterType.h" using namespace std; MeterType::MeterType(void) { } MeterType::MeterType(const string &typeName, const vector<string> &requestedDataItems, const ProtocolFactoryPtr &supportedProtocols) : typeName(typeName), requestedDataItems(requestedDataItems), supportedProtocols(supportedProtocols) { } MeterType::~MeterType() { } const string &MeterType::getTypeName() const { return typeName; } const vector<string> &MeterType::getRequestedDataItems() const { return requestedDataItems; } const ProtocolFactoryPtr &MeterType::getSupportedProtocols() const { return supportedProtocols; } Phew. Quite a list, I know :) . Anyway, to serialize these classes, I wrote the following code: { ofstream ofs("testIt.xml"); archive::xml_oarchive oxml(ofs); oxml << serialization::make_nvp("supportedProtocols", iec1107); } ProtocolFactoryPtr newProtocolFactory; ifstream ifs("testIt.xml"); archive::xml_iarchive ixml(ifs); ixml >> serialization::make_nvp("supportedProtocols", newProtocolFactory); which, however, throws an assert-failure in „basic_iarchive.cpp“ at line 390. Uncommenting that line and recompiling allows me to fully and correctly execute the above code. However, when trying this: { ofstream ofs("testIt.xml"); archive::xml_oarchive oxml(ofs); oxml << serialization::make_nvp("ZMD120", zmd120); } MeterTypePtr newType; ifstream ifs("testIt.xml"); archive::xml_iarchive ixml(ifs); ixml >> serialization::make_nvp("ZMD120", zmd120); The Program crashes with a segmentation fault. Using Insight, i found the very line this happens: It’s in „MeterType.inc“ at line 22: „ar & make_nvp(„SupportedProtocols“, supportedProtocols); Since I imagine this to be more or less exactly the same code as I executed before, without the MeterType class, I’m not quite sure why this should fail. Anyway, can anyone lend me a hand here? Firstly, why would the assertion error occur? And why does serializing ProtocolFactoryPtr one time work and another time fail? Thank you for any help and best regards Kessi _________________________________________________________________ Drück deine Gefühle aus! Hol dir 30 GRATIS Emoticons für den Windows Live Messenger! http://get.live.com

On Thu, 27 Dec 2007 23:30:54 +0000, Pascal Kesseli wrote:
Currently I’m having quite some trouble with the boost serialization library. Take the following classes as given:
Hi, Try executing this test here: http://lists.boost.org/boost-users/att-26574/test_serialize.cpp I had the same problems on gcc 3.2.2 but fortunately was not tied to the compiler. If the above gives you the same issue, then at least the test case is smaller! -- Sohail Somani http://uint32t.blogspot.com
participants (3)
-
Pascal Kesseli
-
Robert Ramey
-
Sohail Somani