0

次のクラスをシリアル化するように定義しました。

using namespace std;

class MyElementObject
{
    friend class boost::serialization::access;

    public:
        template<class Archive>
        void serialize(Archive & ar, const unsigned int version) { }
};

template<class T>
class MyRecursiveObject
{
    friend class boost::serialization::access;

    public:
        T element;
        std::vector<MyRecursiveObject<T> > children;

        template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & element;
            ar & children;
        }
};

次に、次のコードを実行します。

int main()
{
    //MyRecursiveObject initialization
    MyRecursiveObject<MyElementObject> rec_object;    
    rec_object.children.push_back(MyRecursiveObject<MyElementObject>());
    rec_object.children[0].children.push_back(MyRecursiveObject<MyElementObject>());

    //create vector of pointers to MyRecursiveObject's elements
    vector<MyElementObject *> elt_ptrs;
    elt_ptrs.push_back(&rec_object.element);
    elt_ptrs.push_back(&rec_object.children[0].element);
    elt_ptrs.push_back(&rec_object.children[0].children[0].element);

    //serialize MyRecursiveObject and the vector of pointers
    {
        ofstream ofs("filename");
        boost::archive::text_oarchive oa(ofs);
        oa << rec_object;
        oa << elt_ptrs;
    }

    //create new MyRecursiveObject and vector of pointers for deserialization
    MyRecursiveObject<MyElementObject> rec_object_deserialized;    
    rec_object_deserialized.children.push_back(MyRecursiveObject<MyElementObject>());
    rec_object_deserialized.children[0].children.push_back(MyRecursiveObject<MyElementObject>());
    vector<MyElementObject *> elt_ptrs_deserialized;

    //deserialize
    {
        ifstream ifs("filename");
        boost::archive::text_iarchive ia(ifs);
        ia >> rec_object_deserialized;
        ia >> elt_ptrs_deserialized;
    }

    //compare deserialized pointers
    cout<<"elt_ptrs first level="<<elt_ptrs_deserialized[0]
    <<" expected="<<&rec_object_deserialized.element<<endl;

    cout<<"elt_ptrs second level="<<elt_ptrs_deserialized[1]
    <<" expected="<<&rec_object_deserialized.children[0].element<<endl;

    cout<<"elt_ptrs third level="<<elt_ptrs_deserialized[2]
    <<" expected="<<&rec_object_deserialized.children[0].children[0].element<<endl;

    return 0;
}

そして、常に次のような出力が得られます。

elt_ptrs first level=0x7fff57c787c0 expected=0x7fff57c787c0
elt_ptrs second level=0x18e7020 expected=0x18e7020
elt_ptrs third level=0xffff8000ab5564f0 expected=0x18e7450

ポインター値からわかるように、要素を指すポインターを MyRecursiveObject の 2 番目の再帰レベルまで逆シリアル化できます。第 3 レベルまたはさらに深いレベルへのポインターを使用してそれを実行しようとすると、デシリアライゼーションは失敗します。

boost::serialization を間違って使用していますか?

MyRecursiveObject は、再帰レベルの数に関係なく、常に正常に逆シリアル化されることに注意してください。その要素へのポインターを逆シリアル化するだけで問題が発生します。

事前にありがとうキーン

4

1 に答える 1

3

まず何が問題なのかを調べてみましょう。デフォルトのコンテナー デシリアライザーは、基本的に次のように機能します。

size_t count;
ar >> BOOST_SERIALIZATION_NVP(count); // get element count
while( count-- > 0 ) {
    T temp; // <- and here's the problem!
    ar >> boost::serialization::make_nvp("item",temp);
    container.push_back(temp);
}

コンテナー (あなたの場合はvector<MyRecursiveObject<T>>) は、ローカル変数を使用して埋められます。残念ながら、それらのアドレスは登録 (オブジェクト追跡) され、 を逆シリアル化するときに参照されますvector<MyElementObject*>。言い換えれば、あなたelt_ptrs_deserializedはずっと前になくなったローカル変数を指しています。

これを修正するには、ローカル変数を使用せずにベクターを手動でシリアル化します。

template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
    ar & BOOST_SERIALIZATION_NVP(element);
    size_t count = children.size();        // 0 when loading, N when storing
    ar & BOOST_SERIALIZATION_NVP(count);   // load or store element count
    children.resize(count);                // should be a no-op when storing
    while( count-- > 0 )
        ar & boost::serialization::make_nvp("item",children[count]);
}
// You should split serialize() into load() and save() with
// BOOST_SERIALIZATION_SPLIT_MEMBER() for a cleaner version

これで、ベクトル全体のメモリが最初に割り当てられ、要素が直接逆シリアル化されるため、正しいメモリ アドレスが登録されます。これにより、目的の結果が得られるはずです。

elt_ptrs 1st level=0x22fe90 expected=0x22fe90
elt_ptrs 2nd level=0x6127d0 expected=0x6127d0
elt_ptrs 3rd level=0x613d50 expected=0x613d50
elt_ptrs 4th level=0x613c88 expected=0x613c88
于 2012-11-28T23:52:07.103 に答える