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 :

Allocation/Desallocation de mémoire


Sujet :

C++

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

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Par défaut Allocation/Desallocation de mémoire
    Bonjour,

    voilà je m'entraine à faire des allocations dynamiques de tableaux, mais j'ai un doute quant à la qualité de mes désallocations, est-ce que quelqu'un pourrait me dire si les désallocations de mémoire dans le code ci-dessous sont correctes (je me pose la question, car quand j'appelle delete [] tab2, il appelle le destructeur de l'objet, et j'ai dont l'impression qui détruire une adresse déjà détruite et je n'arrive pas à comprendre pourquoi) :

    Hello.cpp
    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
    #include "Hello.hpp"
    #include <iostream>
    using namespace std;
    Hello::Hello(char name[])
    {
         cout<<"Construction d'un objet name a l'adresse : "<<this<<endl;
         this->name = new char;
         strcpy(this->name,name);
    }
    Hello::~Hello()
    {
         cout<<"Destruction d'un objet name a l'adresse : "<<this<<endl;
         delete name;
    }
    void Hello::affiche()
    {
         cout<<"Hello "<<name<<endl;
    }

    Hello.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #ifndef Hello_HPP
    #define Hello_HPP
    class Hello{
          public:
                 Hello(char[] = "Defaut");
                 ~Hello();
                 void affiche();
          private:
                  char *name;
    };
    #endif
    testhello.cpp
    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
    #include "Hello.hpp"
    #include <conio.h>
    Hello *testTab(int nbObjets)
        {
             Hello *tab = new Hello[nbObjets];
             return tab;
        }
    int main()
    {
        int nbObjets = 3;
        Hello *tab2 = testTab(nbObjets);
        for(int i=0;i<nbObjets;i++)
        {
        tab2[i].affiche();
        }
        Hello hello("Toto");
        hello.affiche();
        hello.new_name("Titi");
        hello.affiche();
        hello.~Hello();
        for(int j=0;j<nbObjets;j++)
        {
                 tab2[j].~Hello();
        }
        delete [] tab2;
        getch();
    }
    Merci.

  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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Là tu alloues un caractère, pas une chaîne.

    Ne jamais appeler un destructeur explicitement, delete[] le fera tout seul.

    Pareil, le destructeur sera appelé automatiquement à la fin de la fonction, puisque hello est déclaré localement.

    Conclusion de l'histoire : si tu utilises std::string pour les chaînes et std::vector pour les tableaux, ton code tiendrait en 10 lignes et serait beaucoup plus sûr.

    Voir la

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

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Par défaut
    lol j'en suis pas encore au niveau des vecteurs, et pour les strings ben en fait je fais un TP donc je dois le suivre et c'est un entrainement pour l'allocation des tableaux, heu pour le truc this->name = new char, en fait j'ai remarqué que je mette new char[strlen(name)], ou que je mette new char [1ou2ou3ou n'importe quelle autre valeur], il prend quand même la taille de la chaine de caractère qu'on lui passe (dans ce cas "Toto"==>4), on m'a dit que c'était peut être une optimisation de Dev C++ mais je sais pas.

    Et sinon si j'ai bien compris, je n'ai pas besoin d'appeller tab2[j].~Hello(), je n'ai qu'a appeller delete [] tab2 ?

  4. #4
    Membre émérite

    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2005
    Messages
    634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2005
    Messages : 634
    Par défaut
    Citation Envoyé par Myth_Titans
    lol j'en suis pas encore au niveau des vecteurs, et pour les strings ben en fait je fais un TP donc je dois le suivre et c'est un entrainement pour l'allocation des tableaux, heu pour le truc this->name = new char, en fait j'ai remarqué que je mette new char[strlen(name)], ou que je mette new char [1ou2ou3ou n'importe quelle autre valeur], il prend quand même la taille de la chaine de caractère qu'on lui passe
    Aïe, ceci n'est qu'une impression. Là tu veux écrire dans un espace mémoire que tu n'as pas alloué, si tu alloues juste de la mémoire pour un char et que tu en places 4 ça va crasher un moment ou l'autre...

    Citation Envoyé par Myth_Titans
    Et sinon si j'ai bien compris, je n'ai pas besoin d'appeller tab2[j].~Hello(), je n'ai qu'a appeller delete [] tab2 ?
    Voilà. delete appelle tout seul le destructeur. http://c.developpez.com/faq/cpp/?pag...teur_explicite

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Par défaut
    ben oui c'est ce que je pensais aussi mais pourtant il fonctionne très bien, et si je fais un strlen sur this->name il me donne bien la taille de 4 ("Toto"), de 5 si je met Toto1... mais il vaut mieu que je mette quand même this->name = new char [strlen(name)] je suppose ?

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2005
    Messages
    80
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 80
    Par défaut
    Je trouve l'exercie intéressant, donc je vais posé qq questions:

    Avant cela j'affirme que new char[strlen(name)] est néssècaire ! ( essaye avec une longue chaine )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    char* operator char ();
    /***********/
    char * Hello::operator char ()
    {
         return this->name;
    }
    pourait-on écrire cela ou dans le genre pour permette cela (une convertion)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    cout<<(char)hello<<endl;
    il me met une erreur avec mon compilateur :
    return type specified for `operator char'

    Cette opétateur est-il possible ?

  7. #7
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Il ne faut pas spécifier le type de retour d'un fonction de conversion car celle-ci est donnée par le nom de l'operateur. Dans ton cas, c'est plutôt un char* qu'un char, d'ailleurs.

  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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Citation Envoyé par Myth_Titans
    ben oui c'est ce que je pensais aussi mais pourtant il fonctionne très bien, et si je fais un strlen sur this->name il me donne bien la taille de 4 ("Toto"), de 5 si je met Toto1... mais il vaut mieu que je mette quand même this->name = new char [strlen(name)] je suppose ?
    Oui, car strlen va parcourir la chaîne jusqu'à trouver le 0 final de la chaîne. Donc si par malheur il n'y a aucun crash lorsque tu vas lire la mémoire que tu n'as pas allouée, ça donnera l'illusion de fonctionner. Mais toujours est-il que tu travailles sur un espace mémoire non alloué.

  9. #9
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    A priori, j'aurai mis strlen()+1 pour allouer l'espace pour le \0.

  10. #10
    Membre émérite
    Homme Profil pro
    Consultant ERP
    Inscrit en
    Février 2004
    Messages
    644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant ERP

    Informations forums :
    Inscription : Février 2004
    Messages : 644
    Par défaut
    En gros ça donne ceci

    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
     
    #include <iostream>
    #include <string>
     
    class Hello {
    private:
        std::string name;
    public:
        Hello( const std::string & _name = "Default") : name(_name) {}
        ~Hello() {}
        void Afficher() { std::cout << name << std::endl }
    };
     
    int main( int argc, char ** argv ) {
        Hello hello("Comment allez-vous ?");
        hello.Afficher();
    }

    Voilà

  11. #11
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Tu as compilé ça avec quel compilateur ? Juste pour savoir

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Par défaut
    Merci pour toutes vos réponses, ça a marché ^^.

    Mais maintenant j'ai fait autre chose un peu plus évolué (je suis ce que me demande le TP) voilà le code :

    Hello.cpp
    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
    #include "Hello.hpp"
    #include <iostream>
    using namespace std;
    Hello::Hello(char name[])
    {
         cout<<"Construction d'un objet name a l'adresse : "<<this<<endl;
         this->name = new char[strlen(name)+1];
         strcpy(this->name,name);
    }
    Hello::~Hello()
    {
         cout<<"Destruction d'un objet name a l'adresse : "<<this<<endl;
         delete name;
    }
    void Hello::affiche()
    {
         cout<<"Hello "<<name<<endl;
    }
    Hello.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #ifndef Hello_HPP
    #define Hello_HPP
    class Hello{
          public:
                 Hello(char[] = "Defaut");
                 ~Hello();
                 void affiche();
          private:
                  char *name;
    };
    #endif
    testhello.cpp
    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
    #include "Hello.hpp"
    #include <conio.h>
    Hello **testTabP(int nbObjets)
    {
          Hello **tab = new Hello*[nbObjets];
          char name = 97;
          for(int i=0;i<nbObjets;i++,name++)
          {
          tab[i] = new Hello(&name);
          }
          return tab;
    }
    int main()
    {
        int nbObjets2 = 26;
        Hello **tab3 = testTabP(nbObjets2);
        for(int i=0;i<nbObjets2;i++)
        {
        tab3[i]->affiche();
        }
        delete [] tab3;
        getch();
    }
    Mon problème c'est que quand j'affiche la valeur de chaque objet, il me met 3 caractères supplémentaires (pour l'objet contenant "a", il affiche par exemple "aP%=") et je ne comprend pas pk (je pense que c'est au niveau de mon passage par référence tab[i] = new Hello(&name); mais j'en sais pas plus. Etaussi quand j'appelle delete [] tab3 il ne m'affiche rien, avant il appelais le destructeur mais là il ne le fait plus, mais je pense que c'est parce que je ne l'appelle pas correctement mais je ne sais pas comment faire. Et en fait comme précédemment je voudrais savoir si mes désallocations sont correctes(ce dont e doute fortement) ou non.

    Merci

  13. #13
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Ben c'est normal, tu dis de copier le caractère 97, qui est un a, mais strcpy, strlen, ... cherchent le caractère de fin de chaaîne \0, et quand ils le trouvent, ils arrêtent, donc ils font exactement ce que tu demandes.

  14. #14
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Hello::~Hello()
    {
         cout<<"Destruction d'un objet name a l'adresse : "<<this<<endl;
         delete name;
    }
    Ce serait plutôt delete [], puisque tu alloues avec new [].

    Il faut auparavant détruire les éléments du tableau, puisqu'ils sont également alloués dynamiquement.

    La règles est très simple :
    - new -> delete ; new [] -> delete []
    - chaque new doit avoir son delete

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Par défaut
    ah ok et comment je peux faire pour que il ne stocke QUE 'a' ?

    heu quand tu dis il faut détruire les éléments du tableau, ça veut dire que je dois détruire tab[i] ?

  16. #16
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    1) Tu ne peux pas, tu demandes à copier une chaîne de caractères, 'a' est un caractère, il faudra au moins définir un char* avec "a".
    2) oui.

  17. #17
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    117
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Par défaut
    voilà j'ai un peu modifié la fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Hello **testTabP(int nbObjets)
    {
          Hello **tab = new Hello*[nbObjets];
          char name[2] = {97,'\0'}; 
          for(int i=0;i<nbObjets;i++,name[0]++)
          {
          tab[i] = new Hello(name);
          }
          return tab;
    }
    ça marche mais je veux juste savoir, je n'ai pas touché au reste du code, celà n'affecte pas la gestion de la mémoire j'espère ?

  18. #18
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char name[2] = {97,'\0'}; 
    for(int i=0;i<nbObjets;i++,name[0]++)
    {
        tab[i] = new Hello(name);
    }
    Je vais pinailler un peu : rien ne t'assure que 97 sera le caractère auquel tu penses ('a' ?), et qu'en l'incrémentant tu vas parcourir l'alphabet.
    Une version plus correcte serait par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    const char* Alphabet = "a\0b\0c\0d\0...x\0y\0z\0";
    for(int i=0;i<nbObjets;i++)
    {
        tab[i] = new Hello(Alphabet[i * 2]);
    }

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

    Informations forums :
    Inscription : Avril 2005
    Messages : 117
    Par défaut
    oki merci je vais essayer (je suppose que ce que tu dis arrives quand une machine ne tourne pas sur la table ASCII ?)

  20. #20
    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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Citation Envoyé par Myth_Titans
    oki merci je vais essayer (je suppose que ce que tu dis arrives quand une machine ne tourne pas sur la table ASCII ?)
    C'est ça.

Discussions similaires

  1. [Stratégie]Allocation/Desallocation mémoire
    Par lefait dans le forum Langage
    Réponses: 1
    Dernier message: 08/03/2006, 10h44
  2. allocation/désallocation de mémoire
    Par kinta dans le forum C++
    Réponses: 2
    Dernier message: 10/02/2006, 09h52
  3. Allocation dynamique de mémoire
    Par cd090580 dans le forum Autres éditeurs
    Réponses: 7
    Dernier message: 12/11/2005, 11h17
  4. [VC++/ASM] Allocation dynamique de mémoire ?
    Par Magus (Dave) dans le forum x86 32-bits / 64-bits
    Réponses: 7
    Dernier message: 21/12/2004, 15h05
  5. Allocation dynamique de mémoire en asm
    Par narmataru dans le forum Assembleur
    Réponses: 7
    Dernier message: 17/12/2002, 22h31

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