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 :

Problème de delete


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Inscrit en
    Juin 2007
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 52
    Points : 38
    Points
    38
    Par défaut Problème de delete
    Bonjour,

    Je vais essayer d'être clair:
    J'ai une méthode A qui fait appel a une méthode B. La méthode B utilise des "new". Ma méthode A appel aussi une méthode C qui elle aussi appel la méthode B.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    A
    {
    B[utilisation de new]
    C{B[utilisation de new]}
    }
    Les résultats obtenus de B et de C sont utilisés dans la suite de la méthode A.

    Mon problème est la réalisation de delete qui supprime correctement les new de B.
    En effet je me suis rendu compte que si je fais les delete lorsque je n'ai plus besoin, donc à la fin de la méthode A, seuls les éléments créés en dernier, donc ceux de C sont supprimé, et les premiers ne sont jamais supprimé, ce qui me pose un problème de fuite mémoire.

    Je pense qu'il faut que j'enregistre les adresse des différents pointeurs à supprimer, mais je ne vois pas comment faire.

    J'espère que j'ai été assez clair.

    Merci pour votre aide

  2. #2
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Bonjour,

    je ne sais pas si c'est moi qui ait du mal le lundi matin, mais je n'ai pas tout compris.

    Mais je peux te donner un conseil d'ordre général:
    un fonction qui alloue de la mémoire sur le tas (donc un new) et qui ne le désalloue pas, est très dangereux, et donc il faut éviter. C'est une problématique qui touche à la possession des ressources. Une bonne façon de faire, qui évite de se poser trop de questions, c'est de faire en sorte que jamais une fonction n'alloue sur le tas sans supprimer ce qui a été alloué.

    Typiquement, prenons l'exemple d'un fonction qui créé un tableau d'entier. La première idée qui vient à l'esprit c'est de procéder ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int * CreateArray( const unsigned int size ){
       int * arrayRet = new int[size];
       for ( int i=0; i<size; ++i)
       {
          // code qui rempli le tableau
       }
       return arrayRet;
    }
    La première amélioration consiste à s'assurer que le tableau soit alloué avant. La façon la plus simple de faire cela est de modifier la fonction précédente ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void FillArray( const unsigned int size, int * array ){
       for ( int i=0; i<size; ++i)
       {
          // code qui rempli le tableau
       }
    }
     
    //que l'on utilisera ainsi:
    int * array = new int[size]; //allocation
    FillArray( size, array );
    //... code
    delete [] array; // libération
    Nous voyons dans l'exemple ci-dessus que l'allocation et la libération de font dans la même fonction. C'est le but de la manoeuvre.

    Enfin, la meilleure façon de faire reste quand-même d'utiliser les conteneurs de la stl, évitant ainsi l'allocation brute (new) et la manipulation de pointeurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void FillArray( size_t size , std::vector<int> & array){
       std::vector<int>().swap( array ); // au cas où, on efface le vecteur
       for ( int i=0; i<size; ++i)
       {
          // code qui rempli le tableau. Ici il faudra utiliser la fonction membre push_back de la classe vector
       }
    }
     
    //que l'on utilisera ainsi:
    std::vector<int> array;
    FillArray( size, array );
    // plus besoin de delete: le vecteur est alloué sur la pile, donc supprimé automatiquement en fin de portée
    Hope it helps.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  3. #3
    screetch
    Invité(e)
    Par défaut
    on peut aussi voir que si l'allocation et la liberation sont dans la meme fonction, alors la variable peut devenir locale et etre mise sur la pile au lieu d'appeler new.

    Enfin, si tu ne controles pas la vie de tes pointeurs, tu DOIS les encapsuler dans des structures intelligentes (shared_ptr, auto_ptr) capable de transferer la proprieté.

  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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par damdam78 Voir le message
    Je pense qu'il faut que j'enregistre les adresse des différents pointeurs à supprimer, mais je ne vois pas comment faire.
    Le nœud du problème me semble dans cette phrase: comment fais-tu aujourd'hui pour conserver les adresses des allocations?

  5. #5
    Nouveau membre du Club
    Inscrit en
    Juin 2007
    Messages
    52
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 52
    Points : 38
    Points
    38
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Le nœud du problème me semble dans cette phrase: comment fais-tu aujourd'hui pour conserver les adresses des allocations?
    C'est bien ça le problème, aujourd'hui je ne sais pas comment les enregistrer ces adresses pour pouvoir ensuite les détruire...

    Dans ma méthode B, qui utilise les new, pour le moment c'est enregistré dans un tableau static, donc je peux l'appeler à la fin de ma méthode A, mais ca ne supprime que les new réalisé dans C{B} et non ceux créé dans le 1er B...

  6. #6
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par damdam78 Voir le message
    Dans ma méthode B, qui utilise les new, pour le moment c'est enregistré dans un tableau static
    Comment arrives-tu alors à distinguer dans ta fonction A les objets issus de l'appel à B et ceux de l'appel à C[B]? J'ai l'impression que tout cela est assez confus. Il faut que tu te poses les questions suivantes: quelle est la durée de vie de mes objets alloués et qui y a accès? Il serait intéressant que tu nous expliques un peu le mécanisme que tu as voulu mettre en œuvre pour avoir des aides plus précises.

  7. #7
    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
    Points : 4 625
    Points
    4 625
    Par défaut
    Utilise le RAII.
    Boost ftw

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 369
    Points : 23 623
    Points
    23 623
    Par défaut
    Citation Envoyé par damdam78 Voir le message
    C'est bien ça le problème, aujourd'hui je ne sais pas comment les enregistrer ces adresses pour pouvoir ensuite les détruire...
    Es-tu ab initio en programmation orientée objet ou bien viens-tu déjà d'un autre langage (Java, par exemple) ? Je pose la question parce que les approches ne sont pas les mêmes selon les cas, mais aussi parce que si tu ne sais pas comment conserver les adresses renvoyées par new, je ne vois pas non plus comment tu arrives à exploiter les objets que tu viens de créer.

    Mais comme te l'ont dit Loufoque et 3DArchi, c'est un problème de conception. En gros, dans le cas présent, tu as trois options :

    - Tu exploites le résultat, donc tu n'as pas besoin de conserver les objets proprements dits. Tu fais donc delete juste à la fin de C, dans le même bloc où tu as fait tes new. Et par extension, tu ne fais pas d'allocation sur le tas mais tu utilises le RAII. Tu déclares tes objets en début de bloc comme des variables ordinaires et il seront détruits automatiquement à la sortie ;

    - Le résultat est rendu sous forme d'objet, ou se trouve à l'intérieur de ceux-ci. Dans ce cas-là, même chose. Allocation de l'objet dans la pile et un return sur l'instance. Celle-ci sera donc copiée vers l'objet contenu dans le bloc qui a fait appel à ta méthode avant d'être détruit :

    - C'est un objet très lourd, ou ta méthode B sert explicitement à allouer de nouveaux objets, et dans ce cas-là, ces objets doivent donc être libérés par le bloc qui les exploite. Ta méthode renvoie donc le pointeur généré à la création de tes objets, et le bloc en question doit assimiler cette méthode à un super-new et donc associer un delete à chaque fois qu'elle y fait appel. Tu mets donc des delete partout où tu fais appel à B, donc une fois dans A et une fois dans C.

Discussions similaires

  1. Problème de delete d'une ligne Excel
    Par Charlie47 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 24/08/2006, 14h55
  2. Problème RunSql Delete
    Par lito74 dans le forum Access
    Réponses: 5
    Dernier message: 29/05/2006, 13h13
  3. [version 8.1] problème de delete massif
    Par XPierrot dans le forum DB2
    Réponses: 6
    Dernier message: 12/01/2006, 16h01
  4. [VB]problème avec DELETE
    Par jogu dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 07/01/2006, 10h53
  5. Problème de DELETE
    Par WinZy dans le forum Access
    Réponses: 2
    Dernier message: 21/09/2005, 12h58

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