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

SL & STL C++ Discussion :

Libération de pointeurs dans un std::vector


Sujet :

SL & STL C++

  1. #1
    G
    G est déconnecté
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2002
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Septembre 2002
    Messages : 7
    Points : 1
    Points
    1
    Par défaut Libération de pointeurs dans un std::vector
    Bonjour,

    J'ai une fuite mémoire dans un pg car un vector composé de pointeurs alloués par des new n'est jamais effacé (et les delete ne sont jamais faits ...)

    J'ai regardé la contribution de Loulou24 sur le sujet dans le forum et qui, selon moi, répond à mon besoin ... mais j'ai un souci car je travaille sur des données 'const'.
    Le msg d'erreur est le suivant :
    error C2665: 'delete' : none of the 2 overloads can convert parameter 1 from type 'const tCC *'
    c:\program files\microsoft visual studio\vc98\include\algorithm(37) : see reference to function template instantiation 'int __thiscall Delete::operator ()(const tCC *& ) const' being compiled
    Error executing cl.exe.
    Pour que ce soit plus clair, je vous donne le petit bout de code avec :

    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
    #include <stdio.h>
    #include <vector>
    #include <algorithm>
     
    typedef struct {
     unsigned long idx;
     float valf;
     } tCC;
     
    typedef const tCC* tCCConstPtr;
    typedef std::vector<tCCConstPtr>	ttCCConstPtrVector;
     
    struct Delete
    {
    	template <class T> operator () (T *&p) const
    	{
    		delete p;
    		p = NULL;
    	}
    };
     
    void main(void)
    {
    	ttCCConstPtrVector aCubes;
     
    	tCC* pC = new tCC;
    	pC->idx = 0;
    	pC->valf = 0.0;
    	aCubes.push_back(pC);
     
    	tCC* pC1 = new tCC;
    	pC1->idx = 1;
    	pC1->valf = 1.0;
    	aCubes.push_back(pC1);
     
    	tCC* pC2 = new tCC;
    	pC2->idx = 2;
    	pC2->valf = 2.0;
    	aCubes.push_back(pC2);
     
    	std::for_each(aCubes.begin(), aCubes.end(), Delete());
    }

    Quelqu'un peut-il m'indiquer ce que j'ai mal fait ? Là où ça pêche ?
    Si Loulou24 est dispo, je suis sûr qu'il va me trouver cela rapidement ...

    Merci d'avance.


    [Balises CODE et QUOTE rajoutées par Loulou24, merci d'y penser à l'avenir]

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Tu vas envoyer du const T* à ton foncteur, mais celui-ci attend des T*, donc ça ne passe pas (tu perds le const ). Il faut prendre dans ton foncteur des pointeurs constants ; pour ça il faudra retirer le "p = NULL" (puisque celui-ci sera constant) mais ça ne gène pas dans ton cas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct Delete
    {
       template <class T> operator () (const T *p) const
       {
          delete p;
       }
    };

  3. #3
    G
    G est déconnecté
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2002
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Septembre 2002
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Je viens d'essayer avec un foncteur prenant des mais j'ai le même message d'erreur à la compil.
    Pourtant, il me semblait que ta réponse allait suffire.
    Y'a autre chose qui cloche ...

  4. #4
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    Citation Envoyé par Loulou24
    Tu vas envoyer du const T* à ton foncteur, mais celui-ci attend des T*, donc ça ne passe pas (tu perds le const ). Il faut prendre dans ton foncteur des pointeurs constants ; pour ça il faudra retirer le "p = NULL" (puisque celui-ci sera constant)
    Hmmm, je ne crois pas...
    L'itérateur du vector renvoie bien des const tCC*.
    Du reste, il s'agit bien de pointeurs sur tCC constants, et non pas de pointeurs constants sur tCC. Donc l'instruction "p=NULL", bien qu'inutile, ne gêne pas.

    Accessoirement, je viens de tester le code sur BCC5 et ça passe bien. Juste un warning du compilateur signalant que l'operator() devrait renvoyer quelque chose (ou être déclaré comme renvoyant void). Quel compilateur utilises-tu ?

    NB : J'ai testé avec un à la place du stdio.h, mais je doute que ce soit là l'origine du problème

  5. #5
    G
    G est déconnecté
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2002
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Septembre 2002
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    J'utilise le compilo de Visual C++ (6.0).

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Euh oui effectivement, il manque un void dans la signature de operator ().

    Hmmm, je ne crois pas...
    L'itérateur du vector renvoie bien des const tCC*.
    Du reste, il s'agit bien de pointeurs sur tCC constants, et non pas de pointeurs constants sur tCC. Donc l'instruction "p=NULL", bien qu'inutile, ne gêne pas
    Oui, le paramètre passé sera un const tCC* alors que le foncteur attend un tCC*, donc il y a bien problème. Par contre ok pour le delete NULL, me suis un peu embrouillé.

    Je pense que le problème est que VC6 ne supporte pas le delete d'un pointeur sur constante (c'est pourtant bien autorisé dans la norme).

    Solution : un cast barbare (pour virer le const) ou changement de compilo

  7. #7
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    Grmf... J'avais bien eu quelques soucis avec la STL de Dinkumware dans le temps, mais c'est trop vieux pour que je sois précis là-dessus. Il faudrait jeter un oeil dans leur code pour voir.

    Juste par curiosité, as-tu essayé de remplacer le for_each par une boucle faite à la main pour comparer les compilations ?

  8. #8
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    De toute façon le message est clair : c'est sur delete que porte l'erreur. Le passage par le foncteur fonctionne bien lui.

  9. #9
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    Citation Envoyé par Loulou24
    Oui, le paramètre passé sera un const tCC* alors que le foncteur attend un tCC*, donc il y a bien problème.
    C'est là que j'ai du mal à te suivre, mais d'un autre côté ça fait un bail que je n'ai pas touché au C++
    Alors reprends-moi si je dis des bêtises... mais il me semble que le paramètre template T prend la classe qu'on lui envoie. Il ne fait pas spécialement de filtre sur les modificateurs const, non ?
    Ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template<class T>  foo( T arg ) {... }
    int i = ...; foo( p );  (1)
    int *pi = ...; foo( pi ); (2)
    const int* pci = ...; foo( pci ); (3)
    interprète T comme un int (1), un int* (2) et un const int* (3) respectivement, non ????

    D'ailleurs, si tel est bien le cas, ne suffit-il pas de définir le foncteur comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    struct Delete 
    { 
       template <class T> void operator () ( T &p ) const 
       { 
          delete p;
          p = NULL; 
       } 
    };

  10. #10
    G
    G est déconnecté
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2002
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Septembre 2002
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Je réponds à la question d'Herode : oui j'ai essayé de changer le for_each par un parcours plus "classique" du vecteur et ... je n'ai plus d'erreur de compilation !
    Du coup, j'ai essayé cela dans le code que je dois améliorer (car l'origine du pb est bien de corriger une fuite mémoire) mais je ne vois pas d'effets positifs avec GlowCode.

    Il faut donc que je continue à investiguer ...

  11. #11
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Alors reprends-moi si je dis des bêtises... mais il me semble que le paramètre template T prend la classe qu'on lui envoie. Il ne fait pas spécialement de filtre sur les modificateurs const, non ?
    Avec T en paramètre je pense que oui, ça prendrait bien "const tCC*", mais pas avec T* en paramètre. C'est là que ça coince.
    Tu peux tout à fait prendre un T en paramètre, prendre un T* explicitait juste le fait que ce soit un pointeur.

    Sinon, bizarre que ça passe avec une boucle déroulée à la main M'enfin bon, je suis un peu dans le cirage moi ce matin.

  12. #12
    G
    G est déconnecté
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2002
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Septembre 2002
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Oui c'est bizarre. Personnellement, je ne trouve pas d'explication pour l'instant.

    Mais ce qui me gêne aussi (pour préciser mon dernier post), c'est que Purify m'indique que mon petit bout de code perd autant de mémoire lorsque je fais appel au foncteur que lorsque je ne fais rien (en gros des new et des push_back) sans me soucier de libérer la mémoire. Là, je suis un peu vert ...

  13. #13
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Ce n'est pas le void qui manque ?

  14. #14
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    Citation Envoyé par G
    Oui c'est bizarre. Personnellement, je ne trouve pas d'explication pour l'instant.
    Mais ce qui me gêne aussi (pour préciser mon dernier post), c'est que Purify m'indique que mon petit bout de code perd autant de mémoire lorsque je fais appel au foncteur que lorsque je ne fais rien (en gros des new et des push_back) sans me soucier de libérer la mémoire. Là, je suis un peu vert ...
    Et donc, avec la signature
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <class T> void operator () ( T &p )
    ça ne marche toujours pas ??

  15. #15
    Membre éprouvé Avatar de Herode
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2005
    Messages
    825
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2005
    Messages : 825
    Points : 933
    Points
    933
    Par défaut
    Citation Envoyé par Loulou24
    Sinon, bizarre que ça passe avec une boucle déroulée à la main M'enfin bon, je suis un peu dans le cirage moi ce matin.
    Moi, je trouve ça plutôt rassurant En déroulant la boucle à la main, on évite le passage par le template en appelant directement delete sur l'itérateur dé-référencé. Cela indique bien que le problème se situe au niveau des arguments d'entrée de l'operator() du foncteur.

  16. #16
    G
    G est déconnecté
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2002
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Septembre 2002
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    Non le void n'apporte aucun changement.

  17. #17
    G
    G est déconnecté
    Nouveau Candidat au Club
    Inscrit en
    Septembre 2002
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Septembre 2002
    Messages : 7
    Points : 1
    Points
    1
    Par défaut
    En fait, j'ai résolu mon pb en utilisant qqchose de basique et qui n'a pas la généricité d'un foncteur ...

    Je parcours ma boucle de begin() à end() et je fais un delete de l'élément pointé par l'itérateur (avec un cast à cause du const !) puis je le mets à NULL.

    Je sais, ce n'est pas "glorieux" mais cela répond à mon besoin donc je m'en contente pour l'instant. Par contre, il me reste des zones d'ombre sur les infos que vous m'aviez données et sur le "pourquoi ça ne marche pas" ...

    Merci en tous les cas.

  18. #18
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Citation Envoyé par G
    Je parcours ma boucle de begin() à end() et je fais un delete de l'élément pointé par l'itérateur
    a- (avec un cast à cause du const !)
    b- puis je le mets à NULL.
    a- tu ne devrais pas en voir besoin, sauf si tu fais b-.
    Le compilo râle sur un simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main() {
        const int * i = 0;
        delete i;
        return 0;
    }
    ?

    b- A chaque fois que je l'ai vu appliqué, cela ne servait strictement à rien -- contrairement à d'autres langages le C++ ne nécessite pas que l'on dise au GC de se dépécher en remettant des pointeurs à 0 (oups! "références").
    Soit le vecteur va ensuite être détruit => remettre à 0 est inutile
    Soit les élements détruits doivent être supprimés du vecteur => on fait un erase derrière qui de la même façon retire tout intérêt à la remise à 0 -- clear, même combat.

Discussions similaires

  1. Réponses: 6
    Dernier message: 04/08/2013, 20h56
  2. Suppression dans un std::vector
    Par bobo034 dans le forum SL & STL
    Réponses: 1
    Dernier message: 18/07/2008, 16h16
  3. Libérer des pointeurs dans une std::map
    Par GaldorSP dans le forum SL & STL
    Réponses: 2
    Dernier message: 09/07/2005, 14h42
  4. Réponses: 8
    Dernier message: 26/08/2004, 18h59
  5. Sauvegarde std::vector dans un .ini
    Par mick74 dans le forum MFC
    Réponses: 2
    Dernier message: 12/05/2004, 13h30

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