samedi 26 octobre 2019

Pointer conflict with boost::serialization of a tree

I want to serialize a tree with boost::serialization.

I have a class "cexp_node" whitch looks something like this:

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

    template<class Archive>
    void serialize(Archive & ar, const unsigned in version)
    {
        ar & id;
        ar & children;
        ar & parent;
        ar & isSelected;
    }

    uint32_t id;
    std::map<uint32_t, boost::shared_ptr<cexp_node>> children;
    boost::shared_ptr<cexp_node> parent;
    bool isSelected;
}

And a class cexp_leaf:

class cexp_leaf: public cexp_node {

    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & boost::serialization::base_object<cexp_node>(*this);
        ar & additionalId;
    }

    std::string additionalId;
}

And the tree:

class cexp_tree{

    friend class boost::serialization::access;

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

    boost::shared_ptr<cexp_node> root;
    std::map<uint32_t, boost::weak_ptr<cexp_leaf>> leaves;
}

The tree has a member leaves that holds pointers to all leaves in the tree.

This is how I fill my tree (this function is called for every leaf):

void cexp_tree::parseNodeMembershipsIntoCexpTree(boost::shared_ptr<cexp_node> node, 
                                             uint32_t level, 
                                             std::list<std::string> const& names, 
                                             std::vector<uint32_t> const& level2OtherId){
    if(level==level2community.size()){ //leaf
        for(const std::string & name : names){
            auto newleaf = boost::make_shared<cexp_leaf>(name, node->getId(), node->getOtherId(), node);
            boost::weak_ptr<cexp_leaf> newleaf2 = newleaf;

            uint32_t key = someHashFunktion(name);

            node->getChildren()[key]= newleaf;
            this->cmpsInLeaves[key] = newleaf2;
        }
    }else{ //inner-node
        uint32_t otherID {level2OtherId.at(level)};
        uint32_t ID {node->getChildren().size()};
        auto iter {node->getChildren().lower_bound(otherID)};

        if(iter != node->getChildren().end() && !(node->getChildren().key_comp()(communityID, iter->first)) && !(node->getChildren().empty())){
            cexp_tree::parseNodeMembershipsIntoCexpTree(iter->second, level+1, names, level2OtherId);
        }else{
            auto newNode =boost::make_shared<cexp_node>(otherID, ID, node);
            node->getChildren().emplace(otherID, newNode);
            iter = node->getChildren().find(otherID);
            cexp_tree::parseNodeMembershipsIntoCexpTree(iter->second, level+1, names, level2OtherId);
        }

    }
}

Now when I serialize a cexp_tree I get a boost::archive::archive_exception, what(): pointer conflict.

More specificly I get that exception, when I try to serialize the the cexp_tree::leaves. When I exclude cexp_tree::leaves from the serialization, everything works fine for the rest of the tree.

Can anyone help? Thank you in advance!

Aucun commentaire:

Enregistrer un commentaire