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++

  1. #1
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 42
    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 : 42
    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 : 42
    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.

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

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Mouais...
    En même temps c'est qu'un exemple pour moi ici, pour m'entraîner. Je vais revenir à un truc tranquille, à base de std::list et de pointeurs normaux!

    Merci Mat pour le coup de main, et à bientôt !

  8. #8
    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
    Je ne sais pas si les pointeurs nus vont vraiment résoudre le problème.
    Il faut bien que quelqu'un en soit propriétaire (et les détruise), donc si tu remplaces juste la boost::ptr_list par une std::list + delete dans le destructeur ça ne va rien changer...

    MAT.

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

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Je viens d'avoir encore une interrogation (décidemment ! )

    Du coup si j'implémente ma troupe comme ça :
    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
    struct Troupe : public Cancaneur
    {
    	Troupe() {}
    	~Troupe()
    	{
    		std::list<Cancaneur *>::const_iterator iter = m_troupe.begin();
    		for ( ; iter != m_troupe.end(); iter++)
    		{
    			delete *iter;
    		}
    	}
    	Troupe (const Troupe &);
     
    	void ajouter( Cancaneur * cancaneur)
    	{
    		m_troupe.push_back(cancaneur);
    	}
     
    	void cancaner()
    	{
    		std::list<Cancaneur *>::iterator iter = m_troupe.begin();
    		for(; iter != m_troupe.end(); ++iter)
    		{
    			(*iter)->cancaner();
    		}
    	}
     
    	std::list<Cancaneur *> m_troupe;
    };
    Je file aussi toute responsabilité à ma troupe, car tout est supprimé dans le destructeur! Finalement, y'a pas grand chose qui change, non ?

    EDIT : post en même temps ! Effectivement ça va rien changer...

  10. #10
    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
    Au fait il faut que le destructeur de Cancaneur soit virtuel puisque justement tu détruits des Cancaneurs.

    MAT.

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

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    +1

  12. #12
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Mouarf, c'est là que des fois on aimerait bien un Garbage Collector .

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

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Oui c'est exactement ce que je me dis en ce moment...
    Mais bon il y a toujours moyen de s'en sortir en encapsulant, encapsulant et encore encapsulant afin de donner des responsabilités à nos objets.

    Les dernières nouvelles que j'avais n'étaient pas en faveur d'un GC pour C++ 0x, alors...

  14. #14
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Si c'est ce que vous voulez, vous savez qu'il en existe, et des gratuits ?
    http://www.hpl.hp.com/personal/Hans_Boehm/gc/

    Effectivement, il semble que ça n'entrera pas dans C++0x. Je serais incapable d'analyser complètement le pourquoi.

    Il y a des aspects politiques (des gens qui vivent en vendant des pointeurs intelligents, et qui trouvent qu'un GC ne sert à rien, par principe...). Il y a des aspects de planning. Il y a des aspects techniques, comme les questions de l'interaction de plusieurs GC dans un même programme (avec des DLL, par exemple), le statut peu clair des modificateurs permettant de paramétrer le GC sur un objet (font-ils ou pas partie du système de types...), le risque d'inutilisabilité pour une bibliothèque (et si le programme compile en mode non-gc ?),...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

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

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Merci pour l'info Loïc.
    Cependant je ne souhaite pas en utiliser pour l'instant.

  16. #16
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Si c'est ce que vous voulez, vous savez qu'il en existe, et des gratuits ?
    http://www.hpl.hp.com/personal/Hans_Boehm/gc/

    Effectivement, il semble que ça n'entrera pas dans C++0x. Je serais incapable d'analyser complètement le pourquoi.

    Il y a des aspects politiques (des gens qui vivent en vendant des pointeurs intelligents, et qui trouvent qu'un GC ne sert à rien, par principe...). Il y a des aspects de planning. Il y a des aspects techniques, comme les questions de l'interaction de plusieurs GC dans un même programme (avec des DLL, par exemple), le statut peu clair des modificateurs permettant de paramétrer le GC sur un objet (font-ils ou pas partie du système de types...), le risque d'inutilisabilité pour une bibliothèque (et si le programme compile en mode non-gc ?),...
    Je sais .

    Tu sais ce qu'il vaut par rapport au GC d'OCaml ?

  17. #17
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Je n'ai hélas jamais eu le temps de tester ce GC, ni de tester sérieusement OCaml...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  18. #18
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Celui d'OCaml se base sur le fait que les pointeurs sont impairs ou qqch du style non ? Et les entiers ne sont codés que sur 31bits si je me souviens bien. Ca fait très artificiel comme système

  19. #19
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Pour poukill : si tu as un soucis pour l'effacement des pointeurs, tu peux peut-être construire un petit quelque chose autour de checked_delete sans passer par des shared_ptr. Par contre, il faut que tu détermines bien quand tel ou tel pointeur doit être supprimé, parce que bien qu'il y ait une vérification à la volée (checked ) il faudrait si possible ne pas repasser 10 fois sur le même pointeur. Ce n'est pas parce que tu as une bouée de sauvetage que tu vas te jeter à l'eau, n'est-ce pas ?

  20. #20
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par Matthieu Brucher Voir le message
    Celui d'OCaml se base sur le fait que les pointeurs sont impairs ou qqch du style non ? Et les entiers ne sont codés que sur 31bits si je me souviens bien. Ca fait très artificiel comme système
    Oups, désolé pour le retard...

    Alors oui les pointeurs sont distincts des entiers, j'crois qu'il utilise le bit de signe pour savoir.

    Sinon, oui les entiers sont codés sur 31 bits sur une plateforme 31 bits, mais a priori c'est pas trop un problème, parce que je me dis que si on est amené à manipuler sans arrêt de entiers aussi grands, c'est que l'utilisation des entiers natifs n'est pas adaptée et qu'il faut passer à des trucs genre Bignum.

    C'est en gros ce qui lui permet de ne pas avoir d'entiers boxés de manière simple.

    Et Java il fait comment par exemple ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

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

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