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 :

Delete de listes crées par l'allocation du compilateur


Sujet :

C++

  1. #1
    Débutant
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Points : 332
    Points
    332
    Par défaut Delete de listes crées par l'allocation du compilateur
    Bonjour;

    J'essai de cleaner un programme que je réutilise
    Fait par deux entreprises Une CMM4 l'autre CMM5.
    Cependant je trouve des scories que je ne résoud pas.
    Quand je passe dans le destructeur, le compilateur génère le code de destruction des objets déclarés au niveau de l'objet sur lequel pointe le destructeur.
    Je met l'exemple du code initial à disposition pour comprendre: voila la partie Déclaration de l'objet. Il y a donc deux listes de crée et le compilateur à l'appel du destructeur va générer un code qui détruira les listes. et il se plante dans la detruction de la deuxième liste

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class CNgramer
    {
      private:
        enum enCNramerMethod
        {
          SEARCH_NGRAMS =1,
          DELETE_NGRAMS,
        };
        std::list<std::wstring> wsListTrim1;
        std::list<std::wstring> wsListTrim2;
    Je précise que j'ai supprimé l'appel du programme pour ce test et qu'on est dans un cycle constructeur destructeur sans autre code appelé et donc on peut juger que les données n'ont pas été perverties par d'autres codes.
    J'ai donc codé un destructeur qui détruit explicitement les deux listes et ce code qui marche parfaitement sur la première se plante comme la précédente sur la deuxième
    il y a sept termes dans la 1° liste et deux dans la deuxième liste

    voici le code du destructeur

    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
    CNgramer::~CNgramer()
    {
       std::list<std::wstring>::iterator it;
       it = wsListTrim1.begin();
       while( it != wsListTrim1.end())
       {
          std::wstring *pStr;
          pStr = &(std::wstring)*it;
          delete pStr;
          it++;
       }
       delete &wsListTrim1;
       it = wsListTrim2.begin();
       while( it != wsListTrim2.end())
       {
          std::wstring *pStr;
          pStr = &(std::wstring)*it;
          delete pStr;
          it++;
       }
       wsListTrim2.clear();
       delete &wsListTrim2;
    }
    Puis je déduire que la destruction réussie des données de la deuxième liste exclue une perversion dans ces données ou dois-je chercher dans cette direction?

  2. #2
    Débutant
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Points : 332
    Points
    332
    Par défaut Destructeur de liste qui marche
    Bonjour;

    comme souvent en formulant une discussion j'ai fait des essais pour trouver une solution. J'ai donc déplacé le delete dans le constructeur après utilisation des données et crée les données par un new qui donne une donnée alloué dans la pile (apparemment bien mieux tolérée par le compilateur).
    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
    CNgramer::CNgramer()
    {
        CPOS* pPos;
        std::list<std::wstring> *wsListTrim1;
        std::list<std::wstring> *wsListTrim2;
        std::list<std::wstring>::iterator itStringPos;
        pPos = new CPOS();
        m_bOptionProblem = false;
        wsListTrim1 = new std::list<std::wstring>;
        wsListTrim2 = new std::list<std::wstring>;
        COption::GetShortValue(OPTION_SECTION_CNGRAMER, OPTION_KEYNAME_MIN_NGRAM_DEGREE, m_shMinNgramDegreeOM, &m_shMinNgramDegreeOM);
        COption::GetShortValue(OPTION_SECTION_CNGRAMER, OPTION_KEYNAME_MAX_NGRAM_DEGREE, m_shMaxNgramDegreeOM, &m_shMaxNgramDegreeOM);
        COption::GetShortValue(OPTION_SECTION_CNGRAMER, OPTION_KEYNAME_MIN_PERCENTAGE, m_shMinPercentageOM, &m_shMinPercentageOM);
        COption::GetShortValue(OPTION_SECTION_CNGRAMER, OPTION_KEYNAME_MIN_OCCURENCE, m_shMinOccOM, &m_shMinOccOM);
        COption::GetStringList((std::wstring)OPTION_SECTION_CNGRAMER,(std::wstring)OPTION_KEYNAME_LIST_TRIM1  , *wsListTrim1, wsListTrim1);
        COption::GetStringList((std::wstring)OPTION_SECTION_CNGRAMER,(std::wstring)OPTION_KEYNAME_LIST_TRIM2  , *wsListTrim2, wsListTrim2);
        if(m_bOptionProblem == false)
        {
           itStringPos = wsListTrim1->begin();
           while (itStringPos != wsListTrim1->end())
           {
              enPOS Curpos = pPos->CPOS::GetPOSWithPOSLabel(*itStringPos);
              m_ListTrim1.push_back(Curpos);
              itStringPos++;
           }
           itStringPos = wsListTrim2->begin();
           while (itStringPos != wsListTrim2->end())
           {
              m_ListTrim2.push_back(pPos->CPOS::GetPOSWithPOSLabel(*itStringPos));
              itStringPos++;
           }
        }
        std::list<std::wstring>::iterator it;
       it = wsListTrim1->begin();
       while( it != wsListTrim1->end())
       {
          std::wstring *pStr;
          pStr = &(std::wstring)*it;
          delete pStr;
          it++;
       }
       delete wsListTrim1;
       it = wsListTrim2->begin();
       while( it != wsListTrim2->end())
       {
          std::wstring *pStr;
          pStr = &(std::wstring)*it;
          delete pStr;
          it++;
       }
       delete wsListTrim2;
       delete pPos;
    }

  3. #3
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Citation Envoyé par JeanNoel53 Voir le message
    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
    CNgramer::~CNgramer()
    {
       std::list<std::wstring>::iterator it;
       it = wsListTrim1.begin();
       while( it != wsListTrim1.end())
       {
          std::wstring *pStr;
          pStr = &(std::wstring)*it;
          delete pStr;
          it++;
       }
       delete &wsListTrim1;
       it = wsListTrim2.begin();
       while( it != wsListTrim2.end())
       {
          std::wstring *pStr;
          pStr = &(std::wstring)*it;
          delete pStr;
          it++;
       }
       wsListTrim2.clear();
       delete &wsListTrim2;
    }
    Oula
    Jamais, jamais, jamais il ne faut faire des choses comme delete &wsListTrim1. Le destructeur d'un objet membre est appellé automatiquement lors de la destruction de l'objet qui le possède, si tu l'appeles encore une fois, alors l'objet membre va être détruit deux fois et tout et n'importe quoi peut arriver (par exemple planter sauvagement )

    Si ta classe est réellement comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class CNgramer
    {
      private:
        enum enCNramerMethod
        {
          SEARCH_NGRAMS =1,
          DELETE_NGRAMS,
        };
        std::list<std::wstring> wsListTrim1;
        std::list<std::wstring> wsListTrim2;
    Alors ton destructeur doit ressembler à ça :
    Ben oui, y en pas ! Le destructeur de std::list est automatiquement appelé lors de la destruction de CNgramer qui va à son tour appeller correctement les destructeurs respectifs de chaque wstring.

    La seule exception, c'est si tu as déclaré ta classe comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class CNgramer
    {
      private:
        enum enCNramerMethod
        {
          SEARCH_NGRAMS =1,
          DELETE_NGRAMS,
        };
        std::list<std::wstring*> wsListTrim1;
        std::list<std::wstring*> wsListTrim2;
    Cette fois-ci wsListTrim1 et wsListTrim2 ne maintiennent pas des wstring, mais des pointeurs vers des wstring, et dans ce cas uniquement il faut détruire manuellement chaque wstring dans le destructeur, car par défaut std::list va supprimer les pointeurs, mais pas les objets pointés.
    Dans ce cas on utilise le code la faq et on obtient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ~CNgramer()
    {
    std::for_each(wsListTrim1.begin(), wsListTrim1.end(), Delete());
    std::for_each(wsListTrim2.begin(), wsListTrim2.end(), Delete());
    }
    Ou alors à la main :

    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
     
    ~CNgramer()
    {
        typedef std::list<std::wstring*> ::iterator iterator;
     
        for(iterator it = wsListTrim1.begin() ; it != wsListTrim1.end() ; it++)
       {
           delete &(*it);
       }
     
        for(iterator it = wsListTrim2.begin() ; it != wsListTrim2.end() ; it++)
       {
           delete &(*it);
       }
    }
    Edit : Donc à retenir : Si ta classe possède des membres qui sont des pointeurs, alors il faut détruire manuellement les objets pointés dans le destructeur. Par contre si les membres sont directement des objets (sans l'indirection d'un pointeur) alors leur destruction est automatique et il n'y a rien à faire de spécial.

  4. #4
    Débutant
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Points : 332
    Points
    332
    Par défaut Destruction des éléments constitué par new
    Bonjour et merci

    Je reçois tes avis et te confirme que ce que tu dis est juste, mais je maintien que BCB est très sensibles aux allocations et supporte mieux les new suivie de delete que les objets générés dans la pile et qu'on a un meilleur résultat
    - sur les objets listes en les allouant par un new et en les détruisant après l'utilisation
    - sur les std::wstring en les déclarant dans une variable globale( sic...!)
    à bientôt et toujours merci à vous, c'est utile d'avoir des gens réactifs lorsqu'on est en butte à des problèmes.
    à+

  5. #5
    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 JeanNoel53 Voir le message
    Bonjour et merci

    Je reçois tes avis et te confirme que ce que tu dis est juste, mais je maintien que BCB est très sensibles aux allocations et supporte mieux les new suivie de delete que les objets générés dans la pile et qu'on a un meilleur résultat
    - sur les objets listes en les allouant par un new et en les détruisant après l'utilisation
    - sur les std::wstring en les déclarant dans une variable globale( sic...!)
    à bientôt et toujours merci à vous, c'est utile d'avoir des gens réactifs lorsqu'on est en butte à des problèmes.
    à+
    std::list et std:: (w)string n'ont probablement pas leur objets sur la pile mais bien sur le tas. Quand tu écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::string une_chaine = "tutu";
    une_chaine est sur la pile
    mais la chaîne "tutu" est probablement sur le tas.

  6. #6
    Débutant
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2008
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Localisation : France, Mayenne (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 022
    Points : 332
    Points
    332
    Par défaut et quand ca plante?
    Bonjour,

    Suite aux dernières discussions, je suis revenu en arrière sur tout ça, et j'ai repris simplement le code du constructeur pour détruire les chaines après leur utilisation.
    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
     
           itStringPos = wsListTrim1.begin();
           while (itStringPos != wsListTrim1.end())
           {
              enPOS Curpos = pPos->CPOS::GetPOSWithPOSLabel(*itStringPos);
              m_ListTrim1.push_back(Curpos);
              std::wstring *pStr;
              pStr = &(std::wstring)*itStringPos;
              delete pStr;
              itStringPos++;
           }
           itStringPos = wsListTrim2.begin();
           while (itStringPos != wsListTrim2.end())
           {
              m_ListTrim2.push_back(pPos->CPOS::GetPOSWithPOSLabel(*itStringPos));
              std::wstring *pStr;
              pStr = &(std::wstring)*itStringPos;
              delete pStr;
              itStringPos++;
           }
    le destructeur est vide
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    CNgramer::~CNgramer()
    {
    }
    et les déclarations sont en local
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
      private:
        enum enCNramerMethod
        {
          SEARCH_NGRAMS =1,
          DELETE_NGRAMS,
        };
        std::list<std::wstring> wsListTrim1;
        std::list<std::wstring> wsListTrim2;
    avec tout ça c'est comme avant l'application se plante sur la destruction de la première liste ( wsListTrim1) avec l'affichage de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    inline void  __stl_delete(void* __p) { ::operator delete(__p); }
    Que puis je faire pour quitter l'application sans être agonie d'injures?

  7. #7
    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 JeanNoel53 Voir le message
    Que puis je faire pour quitter l'application sans être agonie d'injures?
    Salut,

    Nul besoin d'appeler explicitement delete sur des objets que tu n'as pas explicitement alloués :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
              pStr = &(std::wstring)*itStringPos;
              delete pStr;
    Est une erreur car
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::list<std::wstring> wsListTrim2;
    En se détruisant, wsListTrim2 appellera les destructeurs de wstring de tous les éléments dans la liste.
    Si tu veux supprimer un élément de la liste, utilises std::list::erase ou std::list::remove.

  8. #8
    screetch
    Invité(e)
    Par défaut
    la regle est simple :
    si tu utilise new, tu vas devoir appeler delete
    si tu utilise new[] tu vas devoir utiliser delete[]
    si tu utilise malloc tu vas devoir utiliser free
    si tu ne les utilise pas, n'utilise ni delete ni free!!!

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

Discussions similaires

  1. Fermeture fenetre crée par code javascript
    Par Kerod dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 27/02/2010, 00h04
  2. Valeur par défaut d'un liste créée par c:foreach
    Par karsmy99 dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 28/02/2007, 10h13
  3. Récupération d'ne liste envoyé par formulaire
    Par Leviathan_72 dans le forum Langage
    Réponses: 5
    Dernier message: 24/11/2005, 09h36
  4. Impossible d'accéder aux tables non créées par dbo
    Par Pete dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 07/10/2005, 14h01
  5. Réponses: 1
    Dernier message: 28/09/2005, 18h10

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