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 :

Destructeur / allocation dynamique de memoire et fuite de memoire


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2014
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 35
    Par défaut Destructeur / allocation dynamique de memoire et fuite de memoire
    Bonjour a tous,

    J'ai un probleme de fuite de memoire sur un programme qui fini par faire planter mon ordinateur :

    donc pour expliquer en gros mon programme. J'ai un objet de type "Figure" qui contient un vecteur d'entier, un vecteur de pointeurs sur d'autres objets de type figure, ainsi que plusieurs parametre entier / char etc.

    Je cre de nombreuses instances de ce type Figure dans un grands vecteur de pointeurs que j'initialise avec new Figure etc...

    Une fois ceci fait je fusionne plusieurs de ces figures entre elles. En gros je les fusionne deux par deux, une des figures recoit les attributs de la seconde et je voudrais detruire la seconde pour liberer completement sa memoire.

    - il me semble que le compilateur se charger automatiquement de liberer la memoire lorsque ceci etait necessaire. Comment cela fonctionne et comment peut on s'assurer que cela soit fait ? (ie. il faut que le compilateur sache que l'on ne se sert plus de l'objet ?)

    - est-ce que utiliser la commande "delete" sur un pointeur sur une "figure" est la bonne solution pour liberer cette memoire ? J'utilise cette fonction mais le programme plante lorsque j'essaye d'acceder a des pointeurs qui ne pointent plus sur rien. J'ai essaye de corriger ce probleme en ajouter une boucle if (pointeur ==NULL) mais la boucle ne marche visiblement pas. Une solution peut-etre pour tester sur un pointeur pointe toujours sur un element ou si cet element a ete detruit ?

    - Une solution alternative que j'utilise est de lancer la fonction "clear" sur les vecteurs de ma class. La classe entiere n'est pas detruite mais la memoire associe aux vecteurs de la ma classe est libere non ? Cela reduit le probleme mais ne le corrige pas completement, que reste-t-il d'un vecteur apres y avoir effectuer un .clear et occupe-t-il toujours de l'espace memoire ?

    - Enfin derniere question concernant le destructeur. Est-il utile de le definir dans ce cas ou le destructeur par default fait le travail ? J'ai du mal a voir dans quel cas definir manuellement le destructeur peut etre utile.

    Merci pour votre aide

  2. #2
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Par défaut
    Bonjour,

    Je vais répondre à tes questions dans l'ordre :

    - Le compilateur ne fait absolument rien si tu ne lui dis pas de le faire, sauf si c'est un comportement qui est prévu par le standard. Si tu alloues statiquement (sur la pile) un objet, il sera détruit à la fin du scope dans lequel il se trouve. Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main() {
      MyClass i; // Appelle le constructeur de MyClass pour i
      {
        YourClass j; // Appelle le constructeur de YourClass pour j
        // ...
      } // Appelle le destructeur de YourClass pour j
    } // Appelle le destructeur de MyClass pour j
    Si tu construits un objet en faisant appel à new, il sera alloué dynamiquement et donc placé sur le tas. Seul un delete pourra détruire l'objet et libérer la mémoire.

    - Lorsque tu utilises delete, l'objet pointé est détruit et la mémoire à cette adresse est libéré mais le pointeur conserve sa valeur. Autrement dit, après un delete, le pointeur pointe toujours sur l'ancienne adresse de l'objet, qui est à présent une adresse invalide. Si tu veux que le pointeur pointe vers nullptr après la destruction de l'objet, il faut que tu le fasses explicitement.

    - clear() se contente de supprimer la totalité des éléments dans un vecteur. Donc sémantiquement, il ne reste plus rien dans ton vecteur ; après techniquement, il prend toujours de la place en mémoire, pour ses propres attributs (ceux qui contiennent la taille, le nombre d'élements, etc.).

    - En effet, si ton destructeur ne fait rien, il est inutile, mais cela est toujours vrai dans le cas où la classe en question n'est pas une base d'une autre classe. En effet, si tu as deux classes : Base et Derived, et Derived hérite de Base ; tu instancies des objets de type Derived, que tu passes à une fonction qui prend des références vers Base et qui détruit ces objets, alors si tu ne déclares pas le destructeur de Base virtuel, le destructeur de Derived ne sera pas appelé, et cela pourra occasionner des fuites de mémoire. Ceci est un exemple de cas où il est nécessaire de définir un destructeur, même si celui-ci ne fait rien.

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Par défaut
    Hello

    Les explications de the Hound sont exactes, à ceci près qu'il existe toujours un destructeur. Si tu ne le déclares pas, le compilateur générera un destructeur par défaut (en l'occurence, non-virtuel comme déjà dit). Le destructeur ne fait pas rien, même si son corps est vide : il libère la mémoire. Après, il ne semble pas que tu aies de l'héritage ?

    Le problème pour toi ici, c'est le vecteur de pointeurs. C++ est en théorie conçu pour que tu n'aies pas à écrire du code complexe de nettoyage de la mémoire. Par conséquent, il te faudrait:
    - Soit un vecteur qui contient des pointeurs intelligents.
    - Soit un vecteur qui contient les instances mêmes des figures.

    Comme il s'agit de figures géométriques, la sémantique de valeur semble parfaitement acceptable ici. Plutôt que d'avoir un vector<Figure*>, choisis un simple vector<Figure>. Tu peux contruire les figures efficacement grâce à emplace_back, et tu peux fusionner les figures efficacement avec la sémantique de mouvement. Si tu vides un tel vecteur avec clear, la mémoire sera proprement libérée.

    Si tu as de l'héritage, ça ne marche plus et il te faudra un vecteur d'autres chose, par exemple de smart pointers.

    Je note qu'une figure contient un vecteur vers d'autres figures. J'imagine que tu n'as pas envie de recopier trouze mille fois une figure utilisée par plein d'autres. A moins que tu n'aies vraiment beaucoup de figures, je seras pour te conseiller de dupliquer les figures quitte à ce que ça te coûte un peu de mémoire : la simplicité de développement gagnée en vaut largement la peine. Si cependant ton programme contient des millions de figures et qu'il te faut économiser la mémoire, alors l'usage du pattern poids mouche peut t'intéresser.

    Je ne sais pas sur quelle plateforme tu développes, mais si tu es sur Linux, valgrind sera ton ami pour traquer les fuites de mémoires et valider tes corrections.

  4. #4
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Par défaut
    Attention : le destructeur en lui-même ne libère pas la mémoire, ou du moins pas celle de l'objet sur lequel il est appelé. L'allocation/déallocation de la zone de mémoire et la construction/destruction d'un objet sont deux choses que le langage différencie. new appelle la routine d'allocation de mémoire (malloc), puis appelle le constructeur de la classe à l'adresse retournée par cette routine. delete appelle le destructeur puis libère la mémoire (free). M'enfin, on va pas chipoter.

    Sinon, comme jblecanard l'a dit, un vecteur de smart pointers est probablement ce qui ressemble le plus à une solution pour ton problème.

  5. #5
    Membre averti
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2014
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 35
    Par défaut
    merci beaucoup pour vos reponses, c'est plus clair maintenant.

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

Discussions similaires

  1. [C] Allocation dynamique de memoire
    Par xc78370 dans le forum C
    Réponses: 9
    Dernier message: 29/11/2006, 18h57
  2. Réponses: 4
    Dernier message: 21/09/2006, 12h45
  3. Allocation Dynamique de Memoire Avec Operateur New
    Par msstaf dans le forum C++Builder
    Réponses: 3
    Dernier message: 30/06/2006, 15h49
  4. Allocation dynamique de memoire
    Par beb30 dans le forum C
    Réponses: 5
    Dernier message: 25/04/2006, 18h06

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