IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Boost C++ Discussion :

[ptr_container] plantage dans le destructeur


Sujet :

Boost C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut [ptr_container] plantage dans le destructeur
    Salut à tous !

    Je suis en train d'implémenter pour m'exercer un pattern basé sur composite / fabrique. Tout marchait très bien jusqu'à ce que je veuille améliorer mon code en introduisant un ptr_list pour mieux gérer ma libération de mémoire. Et là c'est le drame.
    LE problème est qu'il faut toujours passer directement le pointeur à la liste, du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    m_list.push_back( new Elements );
    Et à un endroit du code, celà ne m'est pas possible. Je veux ajouter ma troupe de colvert à ma troupe de canard :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #include <iostream>
    #include <limits>
     
    #include "canard.h"
    #include "fabrique.h"
     
    struct SimulateurDeCanards
    {
    	SimulateurDeCanards()
    	{
    		std::cout << "Simulateur de Canard avec composite" << std::endl;
    		m_fabrique_canard = new FabriqueDeComptage();
    		m_fabrique_oie  =   new FabriqueDOies();
     
    		m_troupe_de_canard  = new Troupe; // Creation d'un objet Composite
    		m_troupe_de_colvert = new Troupe; // Creation d'un objet Composite
     
    		// On remplit la troupe avec la fabrique appropriée
    		m_troupe_de_canard->ajouter(m_fabrique_canard->creerMandarin());
    		m_troupe_de_canard->ajouter(m_fabrique_canard->creerAppelant());
    		m_troupe_de_canard->ajouter(m_fabrique_canard->creerCanardEnPlastique());
    		m_troupe_de_canard->ajouter(m_fabrique_oie->creerOie());
     
    		m_troupe_de_colvert->ajouter(m_fabrique_canard->creerColvert());
    		m_troupe_de_colvert->ajouter(m_fabrique_canard->creerColvert());
    		m_troupe_de_colvert->ajouter(m_fabrique_canard->creerColvert());
    		m_troupe_de_colvert->ajouter(m_fabrique_canard->creerColvert());
     
    		m_troupe_de_canard->ajouter(m_troupe_de_colvert); // Problème ICI lors de l'ajout du composite
    	}
     
    	~SimulateurDeCanards()
    	{
    		delete m_fabrique_canard;
    		delete m_fabrique_oie;
     
    		delete m_troupe_de_canard; // Ces deux lignes sont nécessaires
    		delete m_troupe_de_colvert; // Ca plante plus si je les commente !!!
    	}
     
    	void simuler()
    	{
    		simuler(m_troupe_de_canard);
    		simuler(m_troupe_de_colvert);
    	}
     
    	void simuler(Cancaneur * cancaneur)
    	{
    		cancaneur->cancaner();
    	}
     
    	FabriqueDeCanardsAbstraite * m_fabrique_canard;
    	FabriqueDOies * m_fabrique_oie;
     
    	Troupe *  m_troupe_de_canard;
    	Troupe *  m_troupe_de_colvert;
    };
     
    int main()
    {
    	SimulateurDeCanards simulateur;
    	simulateur.simuler();
     
    	std::cout << "\nNous avons compté " << CompteurDeCouac::getCouacs() << " Couacs\n" << std::endl;
     
    	std::cout << "Appuyez sur entrée pour continuer...";
    	std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
     
    	return 0;
    }
    Si quelqu'un a une idée, qui n'hésite surtout pas !


  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Le boost::ptr_list devient propriétaire des éléments qu'on lui donne, donc soit tu en tiens juste compte en tu ne les re-détruits pas une seconde fois dans ton destructeur, soit tu utilises un conteneur STL 'normal' avec des boost::shared_ptr pour partager la propriété des éléments.

    C'est un peu ce qu'explique la section Motivation de la documentation des ptr_list en fait.

    MAT.

  3. #3
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Hum... Oui bien sûr. Merci Mat !
    Damned, effectivement mon code marche maintenant, mais ça pose un sérieux problème de souplesse. Car les delete que tu mets (ou pas) dans ton destructeur vont dépendre directement de ton implémentation !

    C'est moi où c'est pas génial génial ?

  4. #4
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Dans ton cas ça ne semble pas tellement approprié en effet, si tu veux pouvoir conserver une référence directe sur certains éléments.

    Cela dit en théorie l'intérêt du composite est que, une fois les éléments créés et l'assemblage fait, tu manipules tout à partir d'une seule référence sur le haut de l'arbre, et même pas un 'Troupe' mais bel et bien un 'Canard' (ou l'interface 'Oiseau' ou je sais pas quoi qu'il y aurait au-dessus et que à la fois 'Troupe' et 'Canard' implémenteraient).
    Et donc du coup chaque 'Troupe' serait bien propriétaire de ses canards de manière transparente à l'utilisation.

    Je sais pas si c'est très clair ce que je raconte...

    MAT.

  5. #5
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Si si c'est évidemment très clair. L'intérêt du pattern composite est de manipuler le composite comme n'importe quel élément j'en suis bien conscient.
    De ce fait, le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    struct Cancaneur
    {
    	Cancaneur() {}
    	virtual ~Cancaneur() {}
    	virtual void cancaner() = 0;
    };
     
    struct Troupe : public Cancaneur
    {
    	void ajouter( Cancaneur * cancaneur)
    	{
    		m_troupe.push_back(cancaneur);
    	}
     
    	void cancaner()
    	{
    		boost::ptr_list<Cancaneur>::iterator iter = m_troupe.begin();
    		for(; iter != m_troupe.end(); ++iter)
    		{
    			iter->cancaner();
    		}
    	}
     
    	boost::ptr_list<Cancaneur> m_troupe;
    };
    me paraissait une bonne idée car je ne me souciais plus de quoi que ce soit au niveau du destructeur. Maintenant, j'ai beaucoup perdu en souplesse d'utilisation si je veux ajouter un composite dans un composite... Car ptr_list prend le contrôle de tout.

    Je crois que je vais repartir sur une std::list avec éventuellement des shared_ptr<> à l'intérieur... Qu'en penses-tu ?

  6. #6
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Avec le boost::ptr_list tu peux toujours mettre un composite dans un composite, mais si y'a besoin à côté de garder des références sur les fils c'est peut-être plus délicat à utiliser sans se prendre les pieds dans le tapis.
    C'est un choix !

    Les boost::shared_ptr c'est pas la solution miracle non plus, si on ne fait pas gaffe on peut vite se retrouver avec des références circulaires...

    MAT.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Détecter plantage dans une dll
    Par peijnoob dans le forum C
    Réponses: 2
    Dernier message: 21/06/2007, 09h46
  2. Réponses: 7
    Dernier message: 10/03/2007, 11h08
  3. Plantage dans un onLoadComplete
    Par michpc dans le forum Flash
    Réponses: 3
    Dernier message: 06/02/2007, 11h20
  4. plantage dans l'assignation d'une string privée
    Par Thordax dans le forum C++
    Réponses: 13
    Dernier message: 09/05/2006, 18h43
  5. probleme de delete dans un destructeur
    Par Chewbi dans le forum C++
    Réponses: 6
    Dernier message: 12/03/2006, 00h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo