[serialization] Sets of shared pointers won't load

Hello list, I'm using Visual C++ Express 2008 and Boost 1.42. I have a graph of classes I'm trying to serialise, and I'm using shared_ptrs to manage multiple references to the same object, but I can't deserialise my graph corectly. I get errors like: First-chance exception at 0x7c812afb in sams-6.exe: Microsoft C++ exception: std::basic_string<char,std::char_traits<char>,std::allocator<char>
at memory location 0x03d7f28c.. HEAP[sams-6.exe]: Invalid allocation size - AC1051B4 (exceeded 7ffdefff) First-chance exception at 0x7c812afb in sams-6.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x03c7dc5c.. HEAP[sams-6.exe]: Invalid allocation size - AC1051A8 (exceeded 7ffdefff)
Here are my classes: struct stats_t { friend class boost::serialization::access; typedef int ts_t; size_t bytes, packets; ts_t firstPacketTs, lastPacketTs; stats_t() : bytes(0), packets(0), firstPacketTs(0), lastPacketTs(0) { } private: template<class Archive> void serialize(Archive &ar, unsigned int /* file_version */) { ar & bytes & packets & firstPacketTs & lastPacketTs; } }; struct dest_port_t { friend class boost::serialization::access; endpoint_t endpoint; shp_socket_t socket; bool inUse; stats_t stats; std::string name; boost::asio::ip::udp::endpoint baue; dest_port_t(const endpoint_t &e, const std::string &n=std::string()) : endpoint(e), inUse(false), name(n), baue(boost::asio::ip::address_v4(e.first), e.second) { } private: template<class Archive> void serialize(Archive &ar, unsigned int /* file_version */) { ar & endpoint & name & inUse & stats; } }; typedef boost::shared_ptr<dest_port_t> shp_dest_port_t; typedef std::set<shp_dest_port_t> dest_port_shpset_t; BOOST_SERIALIZATION_SHARED_PTR( dest_port_t ) namespace boost { namespace serialization { template<class Archive> inline void load_construct_data(Archive &ar, dest_port_t *dpp, unsigned int /* file_version */) { endpoint_t endpoint; std::string name; ar >> endpoint; ar >> name; ::new(dpp) dest_port_t(endpoint, name); ar >> dpp->inUse; ar >> dpp->stats; } } } struct dest_t { friend class boost::serialization::access; endpoint_t endpoint; dest_port_shpset_t ports; size_t connections; std::string name; dest_t(const endpoint_t &e=endpoint_t(), const std::string &n=std::string()) : endpoint(e), connections(0), name(n) { } private: template<class Archive> void serialize(Archive &ar, unsigned int /* file_version */) { ar & endpoint & ports & connections & name; } }; typedef boost::shared_ptr<dest_t> shp_dest_t; typedef std::set<shp_dest_t> dest_shpset_t; BOOST_SERIALIZATION_SHARED_PTR( dest_t ) struct source_t { friend class boost::serialization::access; endpoint_t endpoint; size_t connections; stats_t stats; const bool foreign; // True for 'unrecognised' sources. std::string name; source_t(const endpoint_t &e=endpoint_t(), bool f=false, const std::string &n=std::string()) : endpoint(e), connections(0), foreign(f), name(n) { } private: template<class Archive> void serialize(Archive &ar, unsigned int /* file_version */) { ar & endpoint & connections & stats & const_cast<bool &>(foreign) & name; } }; typedef boost::shared_ptr<source_t> shp_source_t; typedef std::set<shp_source_t> source_shpset_t; BOOST_SERIALIZATION_SHARED_PTR( source_t ) struct connection_t { friend class boost::serialization::access; shp_source_t source; shp_dest_port_t dest_port; shp_dest_t dest; stats_t stats; connection_t(const shp_source_t &s, const shp_dest_port_t &dp, const shp_dest_t &d=shp_dest_t()) : source(s), dest_port(dp), dest(d) { } private: template<class Archive> void serialize(Archive &ar, unsigned int /* file_version */) { ar & source & dest_port & dest & stats; } }; typedef std::set<connection_t> connection_set_t; typedef std::map<endpoint_t, connection_set_t> talkspurt_map_t; namespace boost { namespace serialization { template<class Archive> inline void load_construct_data(Archive &ar, connection_t *cp, unsigned int /* file_version */) { shp_source_t src; shp_dest_port_t dest_port; shp_dest_t dest; ar >> src; ar >> dest_port; ar >> dest; ::new(cp) connection_t(src, dest_port, dest); ar >> cp->stats; } } } class UdpWorker : public syn::Thread { protected: size_t errors_; stats_t total_, invalid_, ignored_; dest_shpset_t dests_; source_shpset_t sources_; talkspurt_map_t talkspurtMap_; }; So it's UdpWorker -> dest_shpset_t -> dest_t -> dest_port_shpset_t -> stats_t, UdpWorker -> source_shpset_t -> source_t -> stats_t, UdpWorker -> talkspurt_map_t -> connection_set_t -> shp_source_t etc. The code to save is: void UdpWorker::save() { try { ofstream os(stateFile_.c_str()); boost::archive::text_oarchive oa(os); oa << errors_; oa << total_; oa << invalid_; oa << ignored_; oa << sources_; oa << dests_; oa << talkspurtMap_; } catch (boost::archive::archive_exception &ae) { log("UdpWorker::save(): Error - caught archive_exception \"%s\" while saving to text archive \"%s\".", ae.what(), stateFile_.c_str()); } catch (...) { log("UdpWorker::save(): Error - caught unknown exception while saving to text archive \"%s\".", stateFile_.c_str()); } } And the loading code is very similar: void UdpWorker::load() { try { ifstream is(stateFile_.c_str()); boost::archive::text_iarchive ia(is); ia >> errors_; ia >> total_; ia >> invalid_; ia >> ignored_; ia >> sources_; ia >> dests_; ia >> talkspurtMap_; } catch (boost::archive::archive_exception &ae) { log("UdpWorker::load(): Error - caught archive_exception \"%s\" while loading from text archive \"%s\".", ae.what(), stateFile_.c_str()); } catch (...) { log("UdpWorker::load(): Error - caught unknown exception while loading from text archive \"%s\".", stateFile_.c_str()); } } The archive seems to be written OK, but when loading it seems to load the sources_ set OK and then die on the dests_ set, with the bad_alloc exceptions given above. So the talkspurt_map_t hasn't been tested yet... I've tried the binary archive, but I get pretty much the same error. I'd really appreciate it if someone with a more experienced eye could have a look at my classes and tell me if there's anything suspicious. Is BOOST_SERIALIZATION_SHARED_PTR still required in 1.42? I couldn't find any mention of it in the documentation, but many examples seem to use it. It looks like it's a no-op anyway on this compiler. Thanks very much, John :^P -- John Pallister john@johnp.net john@synchromesh.com
participants (1)
-
John Pallister