Boost::serialization pointeur avec gestion de mémoire externe via unique_ptr

Est ce que c'est juste ?

a marqué ce sujet comme résolu.
Auteur du sujet

Bonjour à tous.

Je souhaite sérialiser une structure d’arbre la relation entre les différents noeuds est assurée par des pointeurs nus (ie T*) et la mémoire est gérée par unvector<unique_ptr<T>> à coté.

Pour assurer la sérialisation, je teste boost::serialization et les premières expérimentations m’impressionnent. La bibliothqèe arrive à reconstruire une structure d’arbre en mémoire avec assez peu d’effort.

Le problème, c’est que les pointeurs nus deviennent responsable de la mémoire ! Et ca c’est pas cool du tout. Il faut donc re-transférer la gestion de la mémoire au vecteur qui va bien.

J’ai une solution illustrée dans le code ci dessous. En guise de test, je créer 10 objets de A et je vais stocker un tableau qui contient 2 fois chaque objet sous forme de pointeur. Ca sert à simuler les noeuds partagés que j’ai dans mon arbre. Lors de la relecture, je vais créer après avoir tout lu, un unique_pointeur pour chaque pointeur lu, en prenant garde d’éviter d’en créer si l’adresse est déjà présente dans la liste (pour éviter un double delete).

Le seul problème que je vois, c’est qu’entre la lecture du tableau et la création des unique_ptr, la mémoire n’est géré par personne. Mais je survirai

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/vector.hpp>

#include <iostream>
#include <vector>
#include <fstream>
#include <memory>

struct A{
  int i;

  A(int n):i(n){}

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

private:
  friend class boost::serialization::access;
  A() = default;

};

struct Test {
  std::vector<std::unique_ptr<A>> mem_store;
  std::vector<A*> to_store;
  Test() = default;
  Test(bool) {
    for (int i = 0; i < 10; ++i) {
      mem_store.push_back(std::make_unique<A>(i));
    }

    for (int n = 0; n < 2; ++n) {
      for (auto const &ptr : mem_store) {
        to_store.push_back(ptr.get());
      }
    }
  }

private:
  friend class boost::serialization::access;


  template <class Archive>
  void save(Archive &ar, const unsigned int version) const {
    ar &to_store;
  }

  template <class Archive> void load(Archive &ar, const unsigned int version) {
    ar &to_store;
    for (auto ptr_raw : to_store) {
      if (std::find_if(mem_store.begin(), mem_store.end(),
                       [ptr_raw](auto const &stored_ptr) {
                         return ptr_raw == stored_ptr.get();
                       }) == mem_store.end()) {
        mem_store.push_back(std::unique_ptr<A>(ptr_raw));
      }
    }
  }
  BOOST_SERIALIZATION_SPLIT_MEMBER()

};


BOOST_CLASS_EXPORT_GUID(Test, "Test");
BOOST_CLASS_EXPORT_GUID(A, "A");
void store() {
  // create and open a character archive for output
  std::ofstream ofs("arxiv");
  boost::archive::text_oarchive oa(ofs);
  Test t{true};
  oa << t;
}

void reload() {
  // create and open an archive for input
  std::ifstream ifs("arxiv");
  boost::archive::text_iarchive ia(ifs);

  Test t;
  ia >> t;

  for (auto ptr_raw : t.to_store) {
    std::cout << ptr_raw <<" "<<ptr_raw->i<<"\n";
  }

  std::cout << "FINAl SIZE " << t.mem_store.size() << "\n";
}

int main() {
  store();
  reload();
  return 0;
}

Valgrind est content, ca marche, mais est ce que c’est juste ? Y’a-t-il autre chose (un bug/une faille) que j’aurai loupé ?

Merci ! David

Édité par Davidbrcz

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte