Opened 14 years ago
Closed 14 years ago
#1942 closed Bugs (wontfix)
Pointers to elements in a std::map are not serilaized correctly
Reported by: | Owned by: | Robert Ramey | |
---|---|---|---|
Milestone: | To Be Determined | Component: | serialization |
Version: | Boost 1.35.0 | Severity: | Problem |
Keywords: | Cc: |
Description
When serializing a std::map and some pointers that are referencing onto elements of that map, those pointers are not loaded correctly.
Here's the code:
#include <sstream> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/map.hpp> struct dummy { template<typename Archive> void serialize(Archive & ar, const unsigned int version) { } }; struct map_ref_test { std::map<std::size_t, dummy> m; dummy * ref; template<typename Archive> void serialize(Archive & ar, const unsigned int version) { ar & m; ar & ref; } }; int main() { std::ostringstream os; map_ref_test m; m.m[0] = dummy(); m.m[1] = dummy(); m.m[2] = dummy(); m.ref = &(m.m[1]); // serialize boost::archive::text_oarchive out(os); out << const_cast<map_ref_test const &>(m); // De-serialize map_ref_test m2; std::string ser = os.str(); std::istringstream is(ser); boost::archive::text_iarchive in(is); in >> m2; std::cout << "0: " << &m.m[0] << std::endl; std::cout << "1: " << &m.m[1] << std::endl; std::cout << "2: " << &m.m[2] << std::endl; std::cout << "ref: " << m.ref << std::endl << std::endl; std::cout << "0: " << &m2.m[0] << std::endl; std::cout << "1: " << &m2.m[1] << std::endl; std::cout << "2: " << &m2.m[2] << std::endl; std::cout << "ref: " << m2.ref << std::endl; }
This creates the following output:
0: 0x805bfc4 1: 0x805bfe4 2: 0x805c004 ref: 0x805bfe4 0: 0x805ca04 1: 0x805ca24 2: 0x805ca44 ref: 0xbfacad5c
I'd expect the last line to read:
ref: 0x805ca24
The code works for std::vectors, so I'd assume it should work for maps also.
Change History (2)
comment:1 by , 14 years ago
comment:2 by , 14 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
After a lot of work, I managed to discover what the problem is.
The following case will fail when all three of the following are true:
a) object is untracked (map<>::value_type in your case
b) object contains something else that is tracked
c) The containing object is moved after being deserialized - load a map has to do.
In your case this can be address by adding:
namespace boost { \ namespace serialization { \ template<> \ struct tracking_level< std::map<std::size_t, dummy>::value_type > \ { \
typedef mpl::integral_c_tag tag; \ typedef mpl::int_< boost::serialization::track_always > type; \ BOOST_STATIC_CONSTANT( \
int, \ value = tracking_level::type::value \
); \
}; } }
I haven't found any general solution. I'll add a note to the documentation.
Robert Ramey
We have the same problem. When an instance of ClassB is serialized, all the saved pointers in map are lost.
We are using Boost 1.35.0 running on Fedora7(64 bits). gcc version 4.1.2
#include <string> #include <map>
#include <boost/serialization/serialization.hpp> #include <boost/serialization/access.hpp> #include <boost/serialization/is_abstract.hpp>
#include <boost/serialization/base_object.hpp> #include <boost/serialization/extended_type_info_typeid.hpp> #include <boost/serialization/export.hpp>
#include <boost/serialization/string.hpp>
#include <boost/mpl/and.hpp> #include <boost/serialization/map.hpp>
using namespace std; using namespace boost::serialization;
class A {
}
class B : public A { private:
protected:
public:
} BOOST_CLASS_EXPORT(B);
class classA { private:
protected:
public:
}
class B {
private:
protected:
public:
}