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

C++ Discussion :

Fuite de mémoire et utilisation de vecteurs contenant des structures en C contenant des pointeurs


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 79
    Points : 26
    Points
    26
    Par défaut Fuite de mémoire et utilisation de vecteurs contenant des structures en C contenant des pointeurs
    Bonjour à tous,
    Dans mon programme en C++ j'utilise une librairie C nommée General Polygon Clipper qui définit la structure gpc_polygon comme suit :
    Code C : 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
    typedef struct                      /* Polygon vertex structure          */
    {
      double              x;            /* Vertex x component                */
      double              y;            /* vertex y component                */
    } gpc_vertex;
     
    typedef struct                      /* Vertex list structure             */
    {
      int                 num_vertices; /* Number of vertices in list        */
      gpc_vertex         *vertex;       /* Vertex array pointer              */
    } gpc_vertex_list;
     
    typedef struct                      /* Polygon set structure             */
    {
      int                 num_contours; /* Number of contours in polygon     */
      int                *hole;         /* Hole / external contour flags     */
      gpc_vertex_list    *contour;      /* Contour array pointer             */
     } gpc_polygon;

    Je dispose également d'une fonction permettant de libérer la mémoire relative à un gpc_polygon :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void gpc_free_polygon(gpc_polygon *p)
    	{
    	int c;
     
    	for (c= 0; c < p->num_contours; c++)
    		FREE(p->contour[c].vertex);
    	FREE(p->hole);
    	FREE(p->contour);
    	p->num_contours= 0;
    	}

    J'utilise dans mon code des std::vector de gpc_polygon, et même des structures C++ ayant comme champ un gpc_polygon voire un std::vector de gpc_polygon ...
    Exemples :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    struct PolygoneDalleAvecInfos
    	{
                  ...
    	gpc_polygon polygone_gpc; 
    	};
     
     
    struct Niveau
    	{
    	...
    	vector<gpc_polygon> polygonesMursInternesEtageInferieurGPC;
    	};
    ensuite j'ai des map du style :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    map<double,vector<PolygoneDalleAvecInfos>> mMap;
    bref c'est compliqué.

    J'ai des fuites de mémoire en pagaille... j'ai compris que c'était dû aux constructeurs par recopie qui ne copiaient que les pointeurs, ainsi qu'à la non-libération de mémoire lorsque ces structures sont détruites... faut-il et peut-on redéfinir l'opération = pour ma structure C ? et pour la libération de mémoire ?

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Dans ton code C++, il te faut créer des classe C++ qui vont se référer à tes structures C, et qui vont gérer la mémoire, notamment leur libération à la destruction des objets de ces classes.

    Mais comme un sommet est je suppose partagé par plusieurs polygones, il va falloir te pencher sur les pointeurs intelligents à comptage de références...

  3. #3
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Hello,

    Citation Envoyé par oodini Voir le message
    Mais comme un sommet est je suppose partagé par plusieurs polygones, il va falloir te pencher sur les pointeurs intelligents à comptage de références...
    Vu le code de libération des polygones, je penche pour une autre explication : chaque polygone possède ses propres vertex. Je peux me tromper, mais si ce n'est pas le cas, alors c'est une gageure de se servir de cette librairie.

    Du coup, le destructeur de Niveau devrait contenir quelque chose du style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Niveau::~Niveau()
    {
      std::for_each(
        polygonesMursInternesEtageInferieurGPC.begin(),
        polygonesMursInternesEtageInferieurGPC.end(),
        libere_polygone());
    }
    Où libere_polygone est le foncteur suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct libere_polygone
    {
      void operator()(gpc_polygone& p)
      {
        gpc_free_polygon(&p);
      }
    }
    Une autre solution consiste effectivement à encapsuler les gpc_polygon dans une classe RAII, de manière à ce que la destruction du vecteur entraine la destruction de toutes les ressources associées à chaque polygone, et ce, de manière automatique.

    Petite remarque sur le nom des variables : si tu as besoin de noms aussi longs, c'est que quelque chose cloche dans ton architecture. Un nom de variable, de méthode ou de fonction est censé être descriptif ET court.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  4. #4
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 79
    Points : 26
    Points
    26
    Par défaut
    Vu le code de libération des polygones, je penche pour une autre explication : chaque polygone possède ses propres vertex.
    Exact.

    Je vais essayer ton exemple avec le destructeur de Niveau...

    Petite remarque sur le nom des variables : si tu as besoin de noms aussi longs, c'est que quelque chose cloche dans ton architecture. Un nom de variable, de méthode ou de fonction est censé être descriptif ET court.
    Alors là je dois reconnaître que mon code n'est pas super simple ni propre, mais c'est dû au manque d'info de mon fichier d'entrée (un .xml parsé), qui m'oblige à faire une 1ère lecture, un traitement, puis une 2e lecture avec prise en compte du résultat du traitement avant une écriture dans un fichier...une vraie horreur.

  5. #5
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 79
    Points : 26
    Points
    26
    Par défaut
    J'ai codé ça comme constructeur par recopie :
    Code C : 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
    void gpc_copy_polygon(gpc_polygon* copie, gpc_polygon* p)
    	{
    	int i, j;
    	copie->num_contours = p->num_contours;
    	MALLOC(copie->hole, p->num_contours * sizeof(int),"hole flag array creation", int);
    	MALLOC(copie->contour, p->num_contours * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list);
    	for (i = 0; i < p->num_contours; i++)
    		{
    		if(p->hole[i] == FALSE)
    			{
    			copie->hole[i] = FALSE;			
    			}
    		else
    			{
    			copie->hole[i] = TRUE;	
    			}
     
    		copie->contour[i].num_vertices = p->contour[i].num_vertices;
    		MALLOC(copie->contour[i].vertex, p->contour[i].num_vertices * sizeof(gpc_vertex), "vertex creation", gpc_vertex);
    		for (j = 0; j < p->contour[i].num_vertices; j++)
    			{
    			copie->contour[i].vertex[j].x = p->contour[i].vertex[j].x;
    			copie->contour[i].vertex[j].y = p->contour[i].vertex[j].y;
    			}
    		}
    	}

    ...Et du coup je code toutes les affectations à la main...

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Citation Envoyé par regliss76 Voir le message
    J'ai codé ça comme constructeur par recopie :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    void gpc_copy_polygon(gpc_polygon* copie, gpc_polygon* p)
    Ça ne ressemble pas à un constructeur de copie.

  7. #7
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 79
    Points : 26
    Points
    26
    Par défaut
    Oui c'est une fonction de copie, le constructeur de copie je ne vois pas trop comment l'écrire, si je le mets dans ma structure C ou pas, ...

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Lis donc cet article.

  9. #9
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par regliss76 Voir le message
    Oui c'est une fonction de copie, le constructeur de copie je ne vois pas trop comment l'écrire, si je le mets dans ma structure C ou pas, ...
    C'est difficile à faire, du C with classes Je te conseille de passer au C++, ça te compliquera moins la vie

    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
     
    namespace 
    {
      gpc_polygon* deep_copy(gpc_polygon* p)
      {
        gpc_polygon* cp = malloc(sizeof(*cp));
        gpc_copy_polygon(cp, p);
        return cp;
      }
    }
     
    class polygon
    {
    private:
      gpc_polygon *m_poly;
     
    public:
      // ce constructeur aquiert le polygone - c'est lui qui le 
      // détruira plus tard. 
      explicit polygon(gpc_polygon* p)
      : m_poly(p)
      { }
     
      polygon() : m_poly(NULL)
      { }
     
      // le constructeur par copie doit faire une copie profonde, 
      // cad copier le contenu et ce qui est contenu dans le contenu
      polygon(const polygon& other)
      : m_poly(deep_copy(other.m_poly))
      { }
     
      ~polygon()
      {
        gpf_free_polygon(m_poly);
      }
     
      // swap idiom : résistant aux exceptions, et facile à écrire !
      polygon& operator=(const polygon& other)
      {
        polygon(other).swap(*this);
        return *this;
      }
     
      void swap(polygon& other)
      {
        std::swap(m_poly, other.m_poly);
      }
     
      // parce qu'il y aura bien des fonctions qui pourront en
      // avoir besoin
      const gpc_polygon* inside() const
      {
        return m_poly;
      }
     
      gpc_polygon* inside()
      { 
        return m_poly;
      }
    };
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  10. #10
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 79
    Points : 26
    Points
    26
    Par défaut
    Merci je tente ça...

    par contre j'ai dû enlever le mot-clé "explicit" sinon ça ne compilait pas, et le malloc(sizeof(*p)) me retourne un void*, pas un gpc_polygon*...

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,
    Citation Envoyé par regliss76 Voir le message
    Merci je tente ça...

    par contre j'ai dû enlever le mot-clé "explicit" sinon ça ne compilait pas, et le malloc(sizeof(*p)) me retourne un void*, pas un gpc_polygon*...
    Honnêtement, tu as tout intérêt à essayer de "virer" le void* aussi vite que possible après la création de ton polygone pour travailler avec le polygone lui-même.

    Il est largement préférable de caster ton void* en gpc_polygon et de transmettre le résultat de ce cast au constructeur de ta classe plutôt que de transmettre un void * au constructeur de ta classe en se disant que l'utilisateur ne se sera pas trompé en passant autre chose, et de tenter le cast du void * en gpc_polygon à l'intérieur du constructeur

    Imagine un peu le constructeur suivant, qui a l'air si génial
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // le compilateur doit nous faire confiance pour le transtypage
    Polygon::Polygon(void ptr):poly( reinterpret_cast<gpc_polygon*>(ptr))
    {
    }
    Mais, en tant qu'utilisateur, je ne vais voir que le prototype du constructeur avec l'intellisens de mon EDI... Imagine ce qui se passerait si je créais une instance de Polygon avec le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
        void * ptr= malloc(sizeof(int),NUMBER_OF_MACHINCHOSE);
        Polygon poly(ptr);
        /* ... */
        return 0;
    }
    qui pourrait me sembler tout à fait correct, et qui serait parfaitement accepté

    Tu serais parti pour des emm... sans noms :p

    Par contre, si tu donnes le constructeur sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Polygon::Polygon(gpc_ploygon * ptr):poly_(ptr){}
    tu inscris dans le "contrat" que l'utilisateur doit impérativement te passer une structure de type gpc_polygon, la manière dont il y arrive ne regardant que lui.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
        void * ptr= malloc(sizeof(int),NUMBER_OF_MACHINCHOSE);
        Polygon poly(reinterpret_cast<gpc_polygon*>(ptr) );
        /* ... */
        return 0;
    }
    tant pis pour lui : il aura "triché" avec le contrat, il n'aura qu'à en subire les conséquences

    D'autant plus que je ne serais pas étonné outre mesure que ta biliothèque fournisse une fonction proche de gpc_polygon * gpc_malloc_polygon(/*...*/ ), et donc, l'utilisateur qui verra, par l'aide de son intellisens ou dans le fichier d'ent-ête, que Polygon requière un gpc_ploygon en argument, trouvera bien un moyen de transmettre un gpc_polygon correctement créé
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 79
    Points : 26
    Points
    26
    Par défaut
    Merci pour cette explication claire !

    Bon voilà j'ai un autre souci...

    La classe Polygone_GPC d'abord :

    Le .h
    Code C++ : 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
     
    #pragma once
    extern "C" 
    	{	
    	#include "gpc.h"
    	}
     
    namespace 
    	{
    	gpc_polygon* deep_copy(gpc_polygon* p)
    		{
    		if(p==NULL)
    			{
    			return NULL;
    			}
    		else
    			{
    			gpc_polygon* cp = (gpc_polygon*)malloc(sizeof(p));
    			gpc_copy_polygon(cp, p);
    			return cp;
    			}
    		}
    	}
     
     
    class Polygone_GPC
    {
    private:
      gpc_polygon* m_poly;
     
    public:
      explicit Polygone_GPC::Polygone_GPC(gpc_polygon* p);
     
      Polygone_GPC::Polygone_GPC();
     
      // le constructeur par copie doit faire une copie profonde, 
      // cad copier le contenu et ce qui est contenu dans le contenu
      Polygone_GPC::Polygone_GPC(const Polygone_GPC& other);
     
      Polygone_GPC::~Polygone_GPC();
     
      // swap idiom : résistant aux exceptions, et facile à écrire !
      Polygone_GPC& Polygone_GPC::operator=(const Polygone_GPC& other);
     
      void Polygone_GPC::swap(Polygone_GPC& other);
     
      // parce qu'il y aura bien des fonctions qui pourront en
      // avoir besoin
      const gpc_polygon* Polygone_GPC::inside() const;
     
      gpc_polygon* Polygone_GPC::inside();
    };

    Le .cpp
    Code C++ : 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
     
    #include "StdAfx.h"
    #include "Polygone_GPC.h"
     
    Polygone_GPC::Polygone_GPC(gpc_polygon* p) : m_poly(p)
    	{ }
     
    Polygone_GPC::Polygone_GPC() : m_poly(NULL)
    	{
    	}
     
    // le constructeur par copie doit faire une copie profonde, 
    // cad copier le contenu et ce qui est contenu dans le contenu
    Polygone_GPC::Polygone_GPC(const Polygone_GPC& other) : m_poly(deep_copy(other.m_poly))
    	{ 
    	}
     
    Polygone_GPC::~Polygone_GPC()
    	{
    	gpc_free_polygon(m_poly);
    	}
     
    // swap idiom : résistant aux exceptions, et facile à écrire !
    Polygone_GPC& Polygone_GPC::operator=(const Polygone_GPC& other)
    	{
    	Polygone_GPC(other).swap(*this);
    	return *this;
    	}
     
    void Polygone_GPC::swap(Polygone_GPC& other)
    	{
    	std::swap(m_poly, other.m_poly);
    	}
     
    // parce qu'il y aura bien des fonctions qui pourront en
    // avoir besoin
    const gpc_polygon* Polygone_GPC::inside() const
    	{
    	return m_poly;
    	}
     
    gpc_polygon* Polygone_GPC::inside()
    	{ 
    	return m_poly;
    	}

    Une de mes structures est comme ceci :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    struct PolygoneDalleAvecInfos
    	{
    	// des choses...
    	Polygone_GPC polygone_gpc; 
    	PolygoneDalleAvecInfos() : polygone_gpc() {}
    	};

    Je m'en sers comme ceci :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    vector<PolygoneDalleAvecInfos> candidats_dalles;
    // .....
    if(condition)
    {
    						PolygoneDalleAvecInfos polygone_dalle_avec_type;
     
    	polygone_dalle_avec_type.attr1 = val1;
                   polygone_dalle_avec_type.attr2 = val2;
                   // ...
                   polygone_dalle_avec_type.attrN = valN;
     
    	candidats_dalles.push_back(polygone_dalle_avec_type);
    }

    L'ajout de ma structure dans mon vector ne fonctionne pas... qu'est-ce que je fais d'incorrect ici ???

  13. #13
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Tu passes bien dans ton constructeur de copie ?
    Si oui, il se passe quoi, en debug, dans ta fonction deepcopy ?

    Au fait, gpc_polygon/Polygone_GPC, bof bof...

  14. #14
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 79
    Points : 26
    Points
    26
    Par défaut
    Je passe bien par le constructeur de copie, et par deepcopy() qui renvoie bien NULL puisque je lui donne un gpc_polygon* NULL...

    En fait avant d'effectuer le push_back, mon objet polygone_gpc est bien du type Polygone_GPC (ma classe C++) ; une fois dans le push_back, _Val a son objet polygone_gpc de type gpc_polygon (struct C) !!! J'ai bien spécifié le constructeur explicit pour éviter toute copie implicite. Késaco ?

  15. #15
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Je ne crois sincèrement pas que dalleAvecInfos doive hériter de Polygone_GPC, ne serait ce que parce que:
    • Polygone_GPC a clairement une sémantique de valeur avec son constructeur par copie et son destructeur non virtuel
    • L'on peut envisager le fait que DalleAvecInfos hérite de Dalle (car c'est effectivement une dalle ) et que dalle utilise en interne un polygone pour rendre certains services que l'on attend d'elle, mais une dalle n'est certainement pas un polygone : une dalle, au mieux, c'est un "objet du décors" ou, tout simplement... une dalle
    • Tu devras, parfois, récupérer le Polygone_GPC, voire, carrément, (lorsque tu voudras t'interfacer avec la bibliothèque que tu as choisie) la structure C gpc_polygon, mais tu ne devra JAMAIS (au grand jamais) faire passer ta dalle (qu'elle soit avec info ou non) pour unn Polygone_GPC
    On ne rappellera jamais assez que l'héritage est la relation la plus forte qui puisse réunir deux classes, et que, par conséquent (et peut être de manière un peu paradoxale ) c'est la relation qu'il faut utiliser le moins souvent

    Ce n'est pas parce que tu peut estimer qu'une classe "spécilisée" doit présenter une interface commune avec une classe plus "générique" qu'il faut d'office en conclure que l'héritage est la meilleure solution ! bien au contraire!!!

    Il ne faut opter pour l'héritage que lorsque tu peux effectivement dire qu'une instance de la classe dérivée est, sémantiquement parlant une instance "particulière" de la classe de base.

    Bien souvent, il s'agira en réalité d'une interface "similaire" et donc de, tout simplement invoquer la fonction correspondante du membre adéquat.

    Comme je présumes que tu n'auras sans doute pas que des dalles avec infos, mais que tu en auras aussi sans, tu te trouverais donc dans la situation où :
    • Il existe des dalles (sans infos) qui agrègent un Polygone_GPC ( comprend : qui contienne un Polygone_GPC qui sera détruit en même temps que la dalle qui le contient )
    • Il existe des dalles avec infos qui héritent des dalles (sans infos) parce qu'il est plus que vraisemblable que tu devra régulièrement passer un ensemble de dalles (avec et sans infos) à des fonctions qui devront les gérer... comme des dalles (à l'adaptation des comportement près), ou, en tout cas, ne n'ayant que faire de savoir si elles (les dalles) ont des infos ou non

    Cela se traduirait, en code en quelque chose de proche de
    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
    class Dalle
    {
        public:
            Dalle(Polygone_GPC const & poly):poly_(poly){}
            virtual ~Dalle(){}
            /* tu peux récupérer le polygone pour ton "usage personnel" 
             * mais tu ne peux pas le modifier )
             */
            Polygone_GPC const & polygon() const{return poly_;}
            /* tu ne peux pas pas le modifier "en direct" car cela revient à
             * créer une dalle tout à fait différente :D
             *
             * Par contre, il y a peut etre des comportements propres aux dalles
             * que tu voudra voire apparaitre :D
             */
        private:
            Polygone_GPC poly_;
    };
    /* une dalle avec infos est une dalle qui a, en plus, des informations 
     * particulières
     */
    class DalleAvecInfo : public Dalle
    {
        public:
            DalleAvecInfo(Polygone_PGC const & poly, Info const & inf):
            Dalle(poly), info_(inf){}
            /* il en va de même pour l'info que pour le polygone de la dalle ;-) 
             */
           Info const & info() const{return info_;}
        private:
           Info info_;
    };
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  16. #16
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 79
    Points : 26
    Points
    26
    Par défaut
    Je ne crois sincèrement pas que dalleAvecInfos doive hériter de Polygone_GPC
    Ce n'est pas le cas.

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    struct PolygoneDalleAvecInfos
    	{
    	// des choses...
    	Polygone_GPC polygone_gpc; 
    	PolygoneDalleAvecInfos() : polygone_gpc() {}
    	};
    Ici la dernière ligne sert à appeler le constructeur par défaut de Polygone_GPC lorsqu'on crée un PolygoneDalleAvecInfos...

    Sinon une simple régénération de la solution a résolu ce souci...

  17. #17
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 79
    Points : 26
    Points
    26
    Par défaut
    J'ai un autre souci (peut-être devrais-je faire un autre sujet, mais bon...).
    Lors de l'instanciation d'un objet Polygone_GPC avec le constructeur par défaut
    l'attribut m_poly de type gpc_polygon* est mis à NULL. OK, ça me semble logique.

    Maintenant je veux utiliser les opérations de clipping de ma biblio :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void gpc_polygon_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip, gpc_polygon *result)
    en faisant un truc du style :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Polygone_GPC temp;
    gpc_polygon_clip(GPC_UNION, contour_gpc.inside(), it_gpc->inside(), temp.inside());

    Evidemment dès qu'on fait un truc du style result->num_contours sur un result valant NULL ça plante... je me demande où faire l'allocation dynamique de mémoire.

    Devrais-je faire :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    gpc_polygon tmp;
    gpc_polygon_clip(GPC_UNION, contour_gpc.inside(), it_gpc->inside(), &tmp);
    Polygone_GPC temp(&tmp);

    Y a-t-il un autre moyen, via la classe Polygone_GPC ?

    Je viens de penser aussi que c'est le cas pour les opérandes, comment effectuer l'opération de clipping avec un ou deux pointeurs pouvant valoir NULL ?

  18. #18
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Citation Envoyé par koala01 Voir le message
    dalle utilise en interne un polygone pour rendre certains services que l'on attend d'elle, mais une dalle n'est certainement pas un polygone : une dalle, au mieux, c'est un "objet du décors" ou, tout simplement... une dalle
    }
    Mouais... ça se discute. Tu opposes la nature géométrique d'un objet à son rôle.
    Une dalle est un parallèpipède, qui est un polyèdre, que certains appellent improprement un polygone, ne t'en déplaise.
    Cette considération ne doit toutefois pas mettre de côté une interrogation légitime : cela doit-il passer par l'héritage ? Il n'y a pas de vérité unique. Un héritage privé sera sans doute le plus adapté, selon moi.

  19. #19
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par oodini Voir le message
    Mouais... ça se discute. Tu opposes la nature géométrique d'un objet à son rôle.
    Une dalle est un parallèpipède, qui est un polyèdre, que certains appellent improprement un polygone, ne t'en déplaise.
    Cette considération ne doit toutefois pas mettre de côté une interrogation légitime : cela doit-il passer par l'héritage ? Il n'y a pas de vérité unique. Un héritage privé sera sans doute le plus adapté, selon moi.
    L'héritage privé n'a de sens que dans de très rares cas. Il introduit des complexités et des subtilités supplémentaires dans le code qui ne sont pas forcément souhaitables.

    La composition est très souvent (et ça a du sens ici) préférable à l'héritage (qu'il soit privé ou public d'ailleurs).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  20. #20
    Nouveau membre du Club
    Inscrit en
    Mai 2007
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 79
    Points : 26
    Points
    26
    Par défaut
    Au secours !
    Memory leaks en folie, malgré tout !
    Exemple dans la fonction suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    vector<Polygone> calculContour(const vector<Polygone>& polygonesDalle,vector<Polygone_GPC>& polygonesMursInternesEtageInferieurGPC,const vector<Polygone>& polygonesMurs, const double altitude)
    	{
    	vector<Polygone> res;
     
    	vector<Polygone_GPC> listePolygonesDalles;
     
    	creer_liste_polygones_gpc(listePolygonesDalles,polygonesDalle); 
                   /* ... */
    	return res; 
                   }
    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
    /*
    méthode créant le polygone "GPC" 2D p à partir d'un Polygone poly
    */
    void creer_polygone_gpc(gpc_polygon *p, Polygone poly)
    	{
    	int i;
    	p->num_contours=1; // 1 seul contour
    	MALLOC(p->hole, p->num_contours * sizeof(int),"hole flag array creation", int);
    	MALLOC(p->contour, p->num_contours * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list);
     
    	p->contour[0].num_vertices = static_cast<int>(poly.size());
     
    	p->hole[0]= false; /*contour extérieur*/
     
    	MALLOC(p->contour[0].vertex, p->contour[0].num_vertices * sizeof(gpc_vertex), "vertex creation", gpc_vertex);
     
    	for (i = 0; i < p->contour[0].num_vertices; i++)
    		{
    		p->contour[0].vertex[i].x = poly[i].x;
    		p->contour[0].vertex[i].y = poly[i].y;
    		}
    	}
     
    /*
    méthode créant le polygone "GPC" 2D p à partir d'un Polygone2D poly
    */
    void creer_polygone_gpc(gpc_polygon *p, Polygone2D poly)
    	{
    	int i;
    	p->num_contours = 1; // 1 seul contour
    	MALLOC(p->hole, p->num_contours * sizeof(int),"hole flag array creation", int);
    	MALLOC(p->contour, p->num_contours * sizeof(gpc_vertex_list), "contour creation", gpc_vertex_list);
     
    	p->contour[0].num_vertices = static_cast<int>(poly.size());
     
    	p->hole[0]= false; /*contour extérieur*/
     
    	MALLOC(p->contour[0].vertex, p->contour[0].num_vertices * sizeof(gpc_vertex), "vertex creation", gpc_vertex);
     
    	for (i = 0; i < p->contour[0].num_vertices; i++)
    		{
    		p->contour[0].vertex[i].x = poly[i].x;
    		p->contour[0].vertex[i].y = poly[i].y;
    		}
    	}
     
    /*
    méthode créant une liste de polygones GPC 2D à partir d'une liste d'objets Polygone
    */
    void creer_liste_polygones_gpc(vector<Polygone_GPC>& listePolygonesGPC,const vector<Polygone>& listePolygones)
    	{
    	for(vector<Polygone>::const_iterator it_p = listePolygones.begin(); it_p != listePolygones.end(); ++it_p)
    		{
    		gpc_polygon p;
    		creer_polygone_gpc(&p,*it_p);
    		Polygone_GPC poly(&p);
    		listePolygonesGPC.push_back(poly);
    		}	// <-- ici le destructeur de Polygone_GPC est bien appelé pourtant 	
    	}
    Je suis perdu... je ne comprends pas d'où cela vient

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

Discussions similaires

  1. Réponses: 11
    Dernier message: 02/12/2013, 20h49
  2. Réponses: 3
    Dernier message: 06/09/2010, 18h26
  3. fuite de mémoire
    Par mamag dans le forum MFC
    Réponses: 17
    Dernier message: 19/08/2005, 10h42
  4. Fuite de mémoire en utilisant le template list
    Par schtroumpf_farceur dans le forum Langage
    Réponses: 9
    Dernier message: 18/07/2005, 20h44
  5. Réponses: 8
    Dernier message: 17/10/2002, 12h52

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