Bonjour à tous,
Je ne comprends pas ce qui se passe, j'ai des shared-ptr qui pointent sur le même pointeur et pourtant il y a double destruction. Pourquoi, dans l'exemple suivant, à la sortie du scope de p2, mon objet Test est détruit ?
Voici le code minimal :
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 | #include<iostream> #include<boost/shared_ptr.hpp> using namespace std; struct Test { int member; Test(): member(123) { cout << "Construction" << endl; } ~Test () { cout << "Destruction" << endl; } void print (int line = -1) { cout << "Affichage à la ligne " << line << ": member=" << member << endl; } }; int main (int argc, char** argv) { Test* x = new Test(); x->print(__LINE__); shared_ptr<Test> p1(x); p1->print(__LINE__); { shared_ptr<Test> p2(x); p2->print(__LINE__); } p1->print(__LINE__); x->print(__LINE__); return 0; } |
ET voici le résultat :
1 2 3 4 5 6 7 8 | Construction Affichage à la ligne 20: member=123 Affichage à la ligne 22: member=123 Affichage à la ligne 25: member=123 Destruction Affichage à la ligne 27: member=2955088 Affichage à la ligne 28: member=2955088 Destruction |
Voici le raisonnement que j'avais et qui est apparament incorrect :
- JE construit un objet Test non encore protégé
- Je crée un shared_ptr p1 qui pointe sur mon objet; son compteur de référence interne est maintenant à 1.
- JE crée le shared_ptr p2; normalement le compteur de référence est censé passer à 2 puisque c'est le même pointeur vers le même objet Test
- ON arrive à la fin du scope de p2, le shared_ptr est détruit, le compteur de référence devrait passer de 2 à 1 et donc mon objet Test ne devrait pas être détruit.
- L'objet Test devrait seulement être détruit en quittant le scope de p1, faisant passer le compteur de référence interne de 1 à 0, à la fin de la fonction main mais pas avant.
Il s'agit bien sûr d'un code minimal reproduisant le problème. Dans le cas réel, mon code s'approche plus de ceci (j'ai tout de même largement simplifié) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Test: std::enable_shared_from_this<Test> { void methode1 (); void methode2 (); }; void fonction (shared_ptr<Test> test) { //... } void Test::methode1 () { fonction( shared_from_this() ); } void Test::methode2 () { //.. } vector<shared_ptr<Test>> tests; tests.push_back(make_shared<Test>(...)); Test& t = *tests[0]; t.methode1(); // OK t.methode2(); // boum! L'objet à été détruit à la fin de methode1, parce que j'ai construit un autre shared_ptr pointant sur le même objet |
Que faire ? Y a-t-il une solution ?
Est-ce que j'ai raté quelque chose d'important dans l'utilisation des shared_ptr et/Ou de enable_shared_from_this ?
Ca me paraît un peu ridicule, si je ne peux pas créer plusieurs shared_ptr qui pointent sur le même objet; je dois forcément avoir fait quelque chose de faux.
Merci pour vos réponses.