| 1 | #include <iostream>
|
|---|
| 2 | #include <vector>
|
|---|
| 3 | #include <fstream>
|
|---|
| 4 | #include <cassert>
|
|---|
| 5 |
|
|---|
| 6 | #include <boost/serialization/vector.hpp>
|
|---|
| 7 | #include <boost/archive/xml_oarchive.hpp>
|
|---|
| 8 | #include <boost/archive/xml_iarchive.hpp>
|
|---|
| 9 |
|
|---|
| 10 | struct dummy {
|
|---|
| 11 | template<class Archive>
|
|---|
| 12 | void serialize(Archive& ar, unsigned int version) {}
|
|---|
| 13 | };
|
|---|
| 14 |
|
|---|
| 15 | int main() {
|
|---|
| 16 | // One-level container
|
|---|
| 17 | // For comparison only. This shows the expected behaviour.
|
|---|
| 18 | {
|
|---|
| 19 | // Create a dummy object in a vector
|
|---|
| 20 | std::vector<dummy> l(1);
|
|---|
| 21 |
|
|---|
| 22 | // Let pd point to that dummy object
|
|---|
| 23 | dummy* pd = &l.back();
|
|---|
| 24 |
|
|---|
| 25 | // Serialize and deserialize the vector and the pointer
|
|---|
| 26 | // Here, the order is important: We have to (de)serialize the vector first,
|
|---|
| 27 | // otherwise we run into an issue similar to what is described at
|
|---|
| 28 | // http://www.boost.org/doc/libs/1_57_0/libs/serialization/doc/exceptions.html#pointer_conflict
|
|---|
| 29 | {
|
|---|
| 30 | std::ofstream ofs("one_level.xml");
|
|---|
| 31 | boost::archive::xml_oarchive oa(ofs);
|
|---|
| 32 | oa << BOOST_SERIALIZATION_NVP(l) << BOOST_SERIALIZATION_NVP(pd);
|
|---|
| 33 | }
|
|---|
| 34 | {
|
|---|
| 35 | std::ifstream ifs("one_level.xml");
|
|---|
| 36 | boost::archive::xml_iarchive ia(ifs);
|
|---|
| 37 | ia >> BOOST_SERIALIZATION_NVP(l) >> BOOST_SERIALIZATION_NVP(pd);
|
|---|
| 38 | }
|
|---|
| 39 |
|
|---|
| 40 | // Thanks to address tracking, pd still points to the dummy object,
|
|---|
| 41 | // even if the latter is loaded at a different address.
|
|---|
| 42 | assert(&l.back() == pd); // Does not fire
|
|---|
| 43 | }
|
|---|
| 44 |
|
|---|
| 45 | std::cout << std::endl;
|
|---|
| 46 |
|
|---|
| 47 | // Two-level container
|
|---|
| 48 | // This is buggy.
|
|---|
| 49 | {
|
|---|
| 50 | // Create a dummy object in a *nested* vector
|
|---|
| 51 | std::vector<std::vector<dummy>> l(1, std::vector<dummy>(1));
|
|---|
| 52 |
|
|---|
| 53 | // Again, let pd point to the dummy object
|
|---|
| 54 | dummy* pd = &l.back().back();
|
|---|
| 55 |
|
|---|
| 56 | // Same as before...
|
|---|
| 57 | {
|
|---|
| 58 | std::ofstream ofs("two_level.xml");
|
|---|
| 59 | boost::archive::xml_oarchive oa(ofs);
|
|---|
| 60 | oa << BOOST_SERIALIZATION_NVP(l) << BOOST_SERIALIZATION_NVP(pd);
|
|---|
| 61 | }
|
|---|
| 62 | {
|
|---|
| 63 | std::ifstream ifs("two_level.xml");
|
|---|
| 64 | boost::archive::xml_iarchive ia(ifs);
|
|---|
| 65 | ia >> BOOST_SERIALIZATION_NVP(l) >> BOOST_SERIALIZATION_NVP(pd);
|
|---|
| 66 | }
|
|---|
| 67 |
|
|---|
| 68 | // Again, we would like pd to point to the dummy object, independent
|
|---|
| 69 | // of where it is loaded. This is not the case, however.
|
|---|
| 70 | assert(&l.back().back() == pd); // Does fire!!!
|
|---|
| 71 | }
|
|---|
| 72 |
|
|---|
| 73 | return 0;
|
|---|
| 74 | }
|
|---|
| 75 |
|
|---|