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 :

Fuites mémoire


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Par défaut Fuites mémoire
    Bonjour à tous,

    J'aimerais savoir si le code suivant produit des fuites mémoires:

    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
     
     
    void CBase::DoSomeThing()
    {  
      CString* pMyString;
      pMyString = new CString();
      pMyString->Empty();
     
      *pMyString = returnastring();
     
      // store pMyString in a Vector that will be freed by CBase::~Dtor..
     
    }
     
    CString CBase::returnastring()
    {
      CString justastring;
      justastring = "Kikoo Dvp";
     
      return justastring;
    }
    Pour moi il en produit mais je ne sais pas comment adapter celà.
    De même, pour la fonction "returnastring", est ce autorisé ce genre d'écriture?? je veux dire, retourner une variable locale et la stocker dans un vecteur qui sera utilisé bien après la mort de la fonction (et donc du destructeur de la cstring locale?)?

    Je dois pas être super bien réveillé, j'ai vraiment du mal avec cette partie..

    S'il faut des précisions, n'hésitez pas

    François

  2. #2
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    Citation Envoyé par squale32 Voir le message
    J'aimerais savoir si le code suivant produit des fuites mémoires
    oui.
    A chaque new doit correspondre un delete.
    Citation Envoyé par squale32 Voir le message
    De même, pour la fonction "returnastring", est ce autorisé ce genre d'écriture?? je veux dire, retourner une variable locale et la stocker dans un vecteur qui sera utilisé bien après la mort de la fonction (et donc du destructeur de la cstring locale?)?
    Oui. C'est une copie qui va être renvoyée.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Par défaut
    Citation Envoyé par spoutspout Voir le message
    oui.
    A chaque new doit correspondre un delete.Oui. C'est une copie qui va être renvoyée.

    Le delete qui correspond au new se trouve plus loin dans le programme. (pointeur stocké dans un vecteur et libéré tout à la fin).

    Quant à la copie retournée, doit-elle est libérée à l'aide d'un delete?


    J'aimerais en fait savoir si à la ligne suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *pMyString = returnastring();
    ... savoir si une deuxième CString est créée ou pas et si je perds le résultat du new 2 lignes plus haut??

    en bref, savoir si à part le delete dans le vector, j'ai autre chose à libérer.

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par squale32 Voir le message
    Bonjour à tous,
    Bonjour à toi,

    Citation Envoyé par squale32 Voir le message
    J'aimerais savoir si le code suivant produit des fuites mémoires:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    void CBase::DoSomeThing()
    {  
      CString* pMyString;
      pMyString = new CString();
      pMyString->Empty();
     
      *pMyString = returnastring();
     
      // store pMyString in a Vector that will be freed by CBase::~Dtor..
     
    }
    Tout dépend ce que tu entend par 'store pMyString in a Vector that will be freed by CBase::~Dtor..'. Sur ta fonction, telle que tu la donnes, le pointeur pMyString est perdu, en toute logique il manque un delete. Mais si tu as omis un bout de code (store blablabla), peut être que le pointeur est mémorisé ailleurs.
    Citation Envoyé par squale32 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CString CBase::returnastring()
    {
      CString justastring;
      justastring = "Kikoo Dvp";
     
      return justastring;
    }
    Pour moi il en produit mais je ne sais pas comment adapter celà.
    De même, pour la fonction "returnastring", est ce autorisé ce genre d'écriture?? je veux dire, retourner une variable locale et la stocker dans un vecteur qui sera utilisé bien après la mort de la fonction (et donc du destructeur de la cstring locale?)?
    Ici, tu ne retourne pas une variable locale mais une copie de cette variable (car ton type de retour est CString et non pas CString&, ou CString*). Donc, pas de soucis. Si tu traces au debugger, tu verras qu'à l'instruction 'return justastring;', tu vas passer d'abord dans le copy-constructeur (pour construrie ta variable de retour), puis dans le destructeur (destruction de ta variable locale justastring). Si tu regardes plus attentivement l'implémentation MFC des CString, tu verras comment la chaîne de caractère est effectivement gérée.

  5. #5
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    remplace
    CString* pMyString;
    pMyString = new CString();
    pMyString->Empty();

    *pMyString = returnastring();
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CString myString = returnastring();
    Mais à mon avis, y'a des problèmes encore plus graves dans ton code.

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

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Ou mieux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CString myString(returnastring());
    Ça évitera la construction d'un objet à vide.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Bonjour à toi,


    Tout dépend ce que tu entend par 'store pMyString in a Vector that will be freed by CBase::~Dtor..'. Sur ta fonction, telle que tu la donnes, le pointeur pMyString est perdu, en toute logique il manque un delete. Mais si tu as omis un bout de code (store blablabla), peut être que le pointeur est mémorisé ailleurs.
    remplacer le commentaire par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      myVector.push_back(pMyString);
     
    }
    Et alors effectivement, à la fin du programme, je boucle dans mon vecteur, j'extrais le pointeur et je le delete. Donc par rapport à cela je pense que je suis bon.

    Ici, tu ne retourne pas une variable locale mais une copie de cette variable (car ton type de retour est CString et non pas CString&, ou CString*). Donc, pas de soucis. Si tu traces au debugger, tu verras qu'à l'instruction 'return justastring;', tu vas passer d'abord dans le copy-constructeur (pour construrie ta variable de retour), puis dans le destructeur (destruction de ta variable locale justastring). Si tu regardes plus attentivement l'implémentation MFC des CString, tu verras comment la chaîne de caractère est effectivement gérée.
    Construction qui nécessite un delete?

    C'est là que se trouve réellement mon problème (au fond de ma tête j'en suis conscient..).

    Il a donc bien 2 allocations à libérer si je comprends bien ce que tu me dis?

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

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par squale32 Voir le message
    Le delete qui correspond au new se trouve plus loin dans le programme. (pointeur stocké dans un vecteur et libéré tout à la fin).
    Si tu es sensible aux fuites mémoire, je te suggère de lire l'article sur les pointeurs intelligents.

  9. #9
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    940
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 940
    Par défaut
    Citation Envoyé par oodini Voir le message
    Ou mieux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CString myString(returnastring());
    Ça évitera la construction d'un objet à vide.
    Il me semble que c'est équivalent à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CString myString = returnastring();
    Pour autant que je me souvienne, l'instruction combinant déclaration et initialisation, c'est directement un appel au constructeur qui est réalisé, et non un création à vide puis l'opérateur d'affectation.

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Oui. J'avais cru voir une paire de () myString.

    Mea culpa.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Par défaut
    Me revoici, désolé pour le temps de réponse...

    Merci pour l'article oodini, je l'avais déjà lu et le trouve effectivement très intéressant, mais malheureusement inapplicable dans le cas qui m'occupe (Projet professionnel avec des vilains délais à tenir ).
    ..Ce code faisant partie des nombreuses portions de code que j'ai à vérifier..

    Sinon, concernant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      CString myString(returnastring());
    cela se trouve dans une boucle et les strings résultantes sont stockées dans un vector qui sera utilisé plus tard dans une autre fonction.
    le new est donc obligatoire je pense ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    void CBase::DoSomeThing()
    {
      while (plusrienafaire)
      {
        CString myString(returnastring());
     
        myVector.push_back( & myString);
      }
     
      // ici mon vecteur ne contient plus rien de bon :/
     
    }
    Dû au nombre de ligne codées autour cette fonction, je ne peux me permettre de changer mon vecteur pour qu'il accepte directement les CString et non plus des pointeurs de cstring..
    De toute façon, niveau occupation mémoire, il est plus intéressant de stocker les pointeurs..

  12. #12
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    940
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 940
    Par défaut
    Citation Envoyé par oodini Voir le message
    Oui. J'avais cru voir une paire de () myString.

    Mea culpa.
    Ok, no soucy

  13. #13
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    Ca ne marchera pas.
    Sorti de ton while, les adresses ne seront plus valides car elles pointent vers des copies de l'élément CString créé par le new et non pas l'élément lui-même qui subsistera jusqu'au delete associé.

  14. #14
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    940
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 940
    Par défaut
    A la base myString était un CString* et non un CString, il me semble qu'il a posté ce code pour montrer qu'avec les modifications qu'il aurait voulu apporter il devenait incohérent (enfin, si j'ai bien compris son intention).

  15. #15
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void CBase::DoSomeThing()
    {
      while (plusrienafaire)
        myVector.push_back(returnastring());
    }
    est la solution optimale dans une implémentation move-aware.

    Après si pour une raison (probablement stupide) tu veux avoir des pointeurs, il faut faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void CBase::DoSomeThing()
    {
      while (plusrienafaire)
        myVector.push_back(new CString(returnastring()));
    }
    qui fera deux copies ou aucune, suivant si CString et ton type vector sont move-aware ou non.

  16. #16
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Par défaut
    Citation Envoyé par Noxen Voir le message
    A la base myString était un CString* et non un CString, il me semble qu'il a posté ce code pour montrer qu'avec les modifications qu'il aurait voulu apporter il devenait incohérent (enfin, si j'ai bien compris son intention).
    C'est effectivement celà, je rajouterais que mon objectif premier était d'éliminer les éventuelles fuites mémoires.
    La question réelle étant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      CString* pMyString;
      pMyString = new CString();
      pMyString->Empty();
     
      *pMyString = returnastring();
    Est ce qu'à la dernière ligne, je perds le résultat du new ?
    Autrement dit, y aura t il 2 delete à faire ou un seul?


    @ loufoque:

    Mais à mon avis, y'a des problèmes encore plus graves dans ton code.
    Après si pour une raison (probablement stupide) tu veux avoir des pointeurs
    Tu ne serais pas un peu provocateur toi ??

    Sinon "move-aware", jamais entendu parler.. Tu peux préciser?

    Les pointeurs j'en ai besoin car la portée du vecteur dépasse celle de la fonction.
    J'ai pris un raccourci que je n'aurais peut être pas du prendre en ne postant qu'une petite partie du code..
    J'avais pas envie de vous mettre 30 pages de code...


    @ spoutspout:
    Effectivement, c'était un contre exemple pour montrer que j'avais besoin des pointeurs..

  17. #17
    Membre éclairé
    Inscrit en
    Mai 2005
    Messages
    73
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 73
    Par défaut
    Ce code ne produit pas de fuites mémoires, il revient au même que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int * pi = new int;
     
    *pi=3;
    (Bien sur, il faut deleter pi plus loin)

  18. #18
    Membre émérite
    Avatar de Spout
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    904
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Février 2007
    Messages : 904
    Par défaut
    Citation Envoyé par squale32 Voir le message
    Est ce qu'à la dernière ligne, je perds le résultat du new ?
    Autrement dit, y aura t il 2 delete à faire ou un seul?
    Un seul, celui associé au new.
    Dans ton code, tu créées un CString quelque part en mémoire en gardant son adresse pour y accéder (= pointeur). Puis tu copies le retour de ta fonction dans ce CString. Tous les éventuels CString qui t'ont servi dans ta fonction returnasstring() auront déjà été supprimés au retour dans le main. Il n'y a que celui quelque part en mémoire à supprimer via le pointeur. Un delete va appeler le destructeur de CString et libérer proprement la-dite mémoire.
    Citation Envoyé par squale32 Voir le message
    Les pointeurs j'en ai besoin car la portée du vecteur dépasse celle de la fonction.
    J'ai pris un raccourci que je n'aurais peut être pas du prendre en ne postant qu'une petite partie du code..
    J'avais pas envie de vous mettre 30 pages de code...


    @ spoutspout:
    Effectivement, c'était un contre exemple pour montrer que j'avais besoin des pointeurs..
    Si tu utilises un vector<CString>, à chaque push_back() ce n'est pas le CString lui-même qui sera inséré dans le vector, mais une copie. Le contenu du vector sera alors toujours valide même après la sortie de la fonction.

    Sinon cela voudrait dire que pour passer d'une fonction à une autre en C++, on aurait pas d'autre choix que de passer par des pointeurs!

  19. #19
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2006
    Messages : 76
    Par défaut
    Merci à tous pour toutes ces précisions,
    Le code ne produit donc pas de fuites mémoires.


    Une dernière question à spoutspout par rapport à sa dernière remarque:

    Si myVector est défini comme suit: vector<CString>;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    CString myString = returnastring();
    myVector.push_back(myString);
    La copie de myString sera t elle détruite toute seule ou vais je devoir appeler moi même le destructeur à l'aide d'un delete?
    D'après moi ce sera fait tout seul par la fonction clear() du vector qui appelle les destructeurs 'direct' des objects stockés (mais pas des pointeurs), suis je dans le bon?


    Encore merci à tous

  20. #20
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par squale32 Voir le message
    La copie de myString sera t elle détruite toute seule ou vais je devoir appeler moi même le destructeur à l'aide d'un delete?
    D'après moi ce sera fait tout seul par la fonction clear() du vector qui appelle les destructeurs 'direct' des objects stockés (mais pas des pointeurs), suis je dans le bon?
    Oui.
    En fait, j'ai l'impression que tu as encore un peu de mal avec les pointeurs, les objets, les copies implicites etc... Tu devrais peut-être jeté un coup d'oeil dans les tuto:http://cpp.developpez.com/cours/

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

Discussions similaires

  1. [tomcat][memoire] java.net.URL et fuite mémoire
    Par Seiya dans le forum Tomcat et TomEE
    Réponses: 6
    Dernier message: 09/03/2009, 10h41
  2. [Fuites mémoire] Je cherche un utilitaire
    Par 10_GOTO_10 dans le forum C++Builder
    Réponses: 8
    Dernier message: 10/02/2005, 10h03
  3. Outil de recherche de fuite mémoire
    Par eag35 dans le forum MFC
    Réponses: 4
    Dernier message: 02/02/2005, 12h46
  4. [SWT]SWT et fuite mémoire(ou pas)
    Par menuge dans le forum SWT/JFace
    Réponses: 2
    Dernier message: 22/06/2004, 21h40
  5. [debug] fuites mémoires
    Par tmonjalo dans le forum C
    Réponses: 3
    Dernier message: 28/07/2003, 17h20

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