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 :

Problem avec Delete


Sujet :

C++

  1. #1
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    36
    D�tails du profil
    Informations personnelles :
    �ge : 39

    Informations forums :
    Inscription : Septembre 2006
    Messages : 36
    Par d�faut Problem avec Delete
    Bonjour a tous
    je suis entrains de me remettre au C++, j'ai encore de bon reste mais j'ai perdu mes reflexs pour comprendre d'ou viennent les erreurs.

    En voici une que je comprend pas ^^:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
     
    Point *p3 = new Point(3,4);
     cout << "ADRESS OF P3: " << &p3 << " value: " << p3->getX() << endl ;
     delete p3; //not forget to free pointed memory
    cout << "ADRESS OF P3: " << &p3 << " value: " << p3->getX() << endl ;
    En sortie:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
     
    int Point::getX()
    ADRESS OF P3: 0xbffff738 value: 3
    Point::~Point()
    int Point::getX()
    ADRESS OF P3: 0xbffff738 value: 3
    Ce que je comprend pas c'est que apres le delete de p3 je puisses encor acceder au valeur pointer par p3.

    Quelqu'un peut m'expliquer?



    Aussi, autre question getsion de memoire, si je creer une variable
    Point p = new point(1,2); je ne peux pas faire delete p.
    Est ce qu'il existe un moyen pour liberer la memoire quand je veus ou est ce que j'attend la fin du bloc?

    cordialement

    jason

  2. #2
    Alp
    Alp est d�connect�
    Expert confirm�

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 36
    Localisation : France, Bouches du Rh�ne (Provence Alpes C�te d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par d�faut
    Alors d�j�, p3 est d�j� un pointeur. Donc le nom p3 co�ncide avec l'adresse de l'objet. Quand tu �cris p3->, cela veut juste dire :
    Bon, tu vas � l'adresse p3, tu regardes ce qu'y s'y trouve.
    Ensuite, si tu fais p3->GetX(), il va simplement aller appeler la fonction GetX() de ta classe Point avec comme objet courant ton objet r�sidant � l'adresse p3.
    Donc (1) : pas besoin de faire &p3.

    Ensuite, en C++, c'est soit :
    soit
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    Point* p = new Point(1.0, 2.0);
    mais ceci n'a aucun sens :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    Point p = new Point(1.0, 2.0); // ça c'est en Java que ça passe
    Le premier, c'est une allocation statique : ton "p" sera d�truit � la fin de la port�e.
    Exemple :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
     
    std::cout << "On va rentrer dans la portée" << std::endl;
    {
      Point p(1.0, 2.0);
      std::cout << "p = (" << p.GetX() << "," << p.GetY() << ")" << std::endl;
    } // pouf, p n'existe plus !
    std::cout << "On est sorti de la portée, p n'existe plus !" << std::endl;
    Ce qui va se passer lorsque l'on arrive � la fin de la port�e, c'est que le destructeur de la classe Point va �tre appel� et ainsi d�truire ton objet p. Il ne sera plus valide. C'est pourquoi faire ceci est une mauvaise id�e :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
     
    Point* f()
    {
      Point p(1.0, 2.0);
      return &p;
    }
    Tu initialises un objet de type Point, et tu retournes son adresse. Or, une fois que la fonction sera termin�e, le destructeur de p sera appel�.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     
    Point* p_ptr = f();
    p_ptr->GetX(); // erreur de segmentation
    Donc tu assignes � p_ptr l'adresse d'un Point qui a �t� d�truit. Ca ne pose pas de soucis... Jusqu'� ce que tu veuille faire quoique ce soit dessus. En effet, les cases m�moires qui �taient prises par ton Point ne sont plus valides, et ne contiennent plus ton Point, donc quand tu vas vouloir appeler GetX(), bam !

    C'est pour contourner les limitations de port�e qu'on utilise encore les pointeurs, auquel cas pas de soucis ici :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Point* f()
    {
      return (new Point(1.0, 2.0));
    }
    // ...
    Point* p = f();
    p->GetX(); // pas de soucis
    Sauf qu'ici, c'est TOI (ou un coll�gue de travail ? ) qui va devoir te charger de d�truire explicitement l'objet allou� dynamiquement (en C++ : new <=> allocation dynamique), via un delete. Tout ce que fait un delete, c'est d�truire l'objet, i.e appeler son constructeur. Ca ne modifie pas l'adresse � laquelle pointait le pointeur, ou quoique ce soit.

    En esp�rant que �a t'aide � comprendre...

    PS : la FAQ regorge de pas mal de Q/Rs qui pourraient bien t'aider � mon avis.

  3. #3
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Salut,

    En fait, tu peux encore obtenir l'adresse de p parce que la variable qui repr�sente le pointeur existe toujours: tu n'as lib�r� que la m�moire se trouvant � l'adresse point�e par p.

    Si tu peux toujours acc�der � p->getX, et surtout avoir un r�sultat coh�rent, ce n'est "que par chance", parce que:
    • L'adresse � laquelle se trouvait la valeur x de ton point n'a pas encore �t� r�utilis�e pour autre chose et les "crasses" qu'elle contient repr�sentes toujours la derni�re valeur repr�sent�e, � savoir... la valeur x de ton point
    • L'adresse � laquelle se trouvait le d�but des donn�es de ton point n'a pas �t� r�utilis�, et l'ensemble de la m�moire qui a servi pour repr�senter ton point contient encore les crasses de son utilisation pr�c�dente, et donc... ce qui permettait de repr�senter ton point.
    • Tu n'acc�de aux diff�rents �l�ments de ce qui �tait ton point qu'en lecture (ici, pour obtenir la valeur de x)... Si tu d�cidais d'y acc�der en �criture (par exemple pour modifier la valeur de x), tu armerais une v�ritable bombe � retardement dont tu n'aurais aucune id�e du moment o� elle "p�tera"


    De plus, si tu venais � invoquer une deuxi�me fois delete sur p, tu enverrais syst�matiquement le compilateur cueillir les marguerites

    C'est la raison pour laquelle une "bonne habitude" � prendre est de syst�matiquement (il y a quelques exceptions pour lesquelles ce n'est pas forc�ment utile, mais pour lesquelles cela ne fait malgr� tout pas de tord) assigner la valeur NULL � un pointeur une fois que tu a demand� la lib�ration de la m�moire de l'adresse point�e.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     
    Aussi, autre question getsion de memoire, si je creer une variable
    point p = new point(1,2); je ne peux pas faire delete p.
    Tu ne peux d�j� pas faire new point dans ce cas, car p n'est pas un pointeur...

    Si tu veux d�clarer une variable normale de type p et l'initialiser directement de mani�re correcte, tu dois, simplement, invoquer le constructeur en lui fournissant les arguments requis sous la forme de:
    voire, si tu veux assigner un nouveau point � ta valeur, sous la forme de
    Il faut noter que l'utilisation de new en C++ n'a strictement rien � voir avec l'utilisation de new que l'on rencontre en java, par exemple...

    En C++, new ne s'applique que lorsqu'il s'agit d'assigner l'adresse d'une variable pour laquelle tu d�cide de prendre toi-m�me la responsabilit� de sa dur�e de vie (c'est � dire que tu es seul responsable du moment o� elle sera effectivement d�truite) � un pointeur.

    Du fait des risques inh�rents � cette man�uvre (risque de double lib�ration de la m�moire ou de fuite m�moire, d�bordement d'index ( essayer de faire entrer N �l�ments dans un tableau dont la m�moire allou�e dynamiquement ne permet que d'en contenir ... N-1), risque d'invalidation du pointeur avec delete, ...) il est largement recommand� de n'y recourir que lorsque l'on n'a vraiment pas le choix, et que l'on sait parfaitement ce que l'on fait.

    Lorsqu'il s'agit "simplement" de manipuler des collections d'objets identiques (ici des points), le C++ fournit de mani�re standard une s�rie de conteneurs qui se chargent tr�s bien de les contenir, allant de la pile au tableau associatif cl� / valeur, en passant par le tableau dont les �l�ments sont contigus, la file, la liste et les arbres binaires (cf l'entr�e de la FAQ quel conteneur choisir pour stocker mes objets?)

    La gestion dynamique de la m�moire n'est pas absente de ces conteneurs, mais elle est utilis�e de mani�re tout � fait transparente en interne, ce qui t'�vite d'avoir � y faire attention toi-m�me .

    Les cas dans lesquels tu auras recours � la gestion dynamique de la m�moire (appel � new / new[] et � delete / delete[]) se limiteront le plus souvent � des cas dans lesquelles tu dispose d'une hi�rarchie de classe lorsque tu souhaite disposer d'objet ayant des comportements polymorphes, en faisant passer un objet comme �tant... du type parent.

    De plus, il sera souvent int�ressant d'utiliser des pointeurs intelligents (shared_ptr, scoped_ptr, unique_ptr, ...) afin de s'assurer que leur gestion se fasse sans heurts
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  4. #4
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    36
    D�tails du profil
    Informations personnelles :
    �ge : 39

    Informations forums :
    Inscription : Septembre 2006
    Messages : 36
    Par d�faut
    OKi doki
    merci pour vos reponses,
    c'est bien ce que je me rappelais de C++
    comme sa fait un moment que je tourne en Java et Objectif-C je suis entrains de faire plain de teste pour remettre les choses au claire.

    Je comprend que une varaible a porte locale sera:

    et que pour gerer la memoire soit meme (allocation et deallocation manuel)

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     
    //Edit: oublie du * pour declarer un pointeur dsl
    Point *point_pointeur = new Point(3,4);
    cependant je voudrais vous corriger/soumettre sur ceci

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    Point p = new Point(5,6);
    avec comme resultat a la compilation:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    Point::Point(int coordX,int coordY)
    Point::Point(Point *pointerPoint)
    Point::~Point()
    (je fais un cout dans chaque constructeur de ma classe point).

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Point::Point(int coordX,int coordY){
        cout << "Point::Point(int coordX,int coordY)" << endl;
        this->x = coordX;
        this->y = coordY;
    }
     
    Point::Point(Point *pointerPoint){
        cout << "Point::Point(Point *pointerPoint)" << endl;
        this->x = pointerPoint->x;
        this->y = pointerPoint->y;
    }
    Enfin tout ce que je fais c'est de recopier les valeurs du pointeur dans le nouveau point.

    Mais comme vous l'avez dit c'est du Java, et surtout sa fait appel a 2 constructeur different pour rien.

    Merci pour vos reponses

    Ps:Alp: Je n'est pas de collegue de travail ^^ je suis entraint de me mettre a jour pour un entretiens de C++ (donc je croise les doigts pour que bientot j'aurais des collegues lol)

  5. #5
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Lorsque tu veux d�clarer un pointeur, il faut une �toile " * " entre le type et le nom de l'objet...
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    Point p = new Point(3,4);
    ne compilera pas... c'est
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    Point * p =new point(3,4); //remarque l'étoile '*' entre Point et p
    qu'il faut �crire
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  6. #6
    Membre �clair�
    Avatar de gb_68
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Ao�t 2006
    Messages
    232
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 41
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Ao�t 2006
    Messages : 232
    Par d�faut
    Bonjour,
    Citation Envoy� par anarkia Voir le message
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    Point p = new Point(5,6);
    avec comme resultat a la compilation:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    Point::Point(int coordX,int coordY)
    Point::Point(Point *pointerPoint)
    Point::~Point()
    oui mais cela n'est possible que parce que tu as d�clar� le constructeur
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    Point::Point(Point *pointerPoint)
    qui n'est pas un constructeur par copie (du point de vue du c++) et est m�me plut�t d�conseill�. Dans le m�me ordre d'id�e il est possible d'�crire pour permettre (attention code affreux )
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    Point p = new int(5); // avec fuite mémoire à la clé
    Le constructeur par copie s'�crit (voir Faq)
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    Point::Point(const Point & OtherPoint){
        cout << "Point::Point(const Point & OtherPoint)" << endl;
        x = OtherPoint.x;
        y = OtherPoint.y;
    }
    Exemple d'usage :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    Point p1(1.0, 2.0);
    Point * p2 = new Point(p1);
    Point p3 = new Point(*p2);
    Point * p4 = new Point(*p2);
    delete p2;
    delete p4;
    Remarque :
    une diff�rence fondamentale � comprendre en C++ par rapport � d'autres langages est la mani�re dont sont consid�r�s les objets.
    Si en Java, les objets ne peuvent �tre manipul�s que par "r�f�rence" (au sens Java ~> pointeurs C++, en un peu plus prot�g�),
    et si en C# et Delphi, les objets peuvent �tre de type valeur ou "r�f�rence" selon le mot cl� employ� (class/struct, class/record) avec les restrictions inh�rentes au type,
    le C++ utilise un seul format de d�finition des objets (class ou struct), mais selon les constructeurs/op�rateurs/fonctions d�finies et/ou interdits (par mise en membre priv�) ces objets sont � utiliser plus par valeur ou par pointeur.

  7. #7
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    36
    D�tails du profil
    Informations personnelles :
    �ge : 39

    Informations forums :
    Inscription : Septembre 2006
    Messages : 36
    Par d�faut
    Merci pour vos reponses
    effectivement j'en etait arriver a plus ou moin la bonne conclusion que
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
     
    Point p = new Point();
    devenait possible seulement a cause de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
     
    Point::Point(Point *p_point);
    c'est comme :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     
    Point p1, p2, p3;
    p3 = p1 + p2;
    Ceci est possible que si l'operateur + a etait surdefinie.


    Comme je l'ais dit plus haut, je suis juste entrain de me remettre au C++ et le meilleur moyen c'est de se mettre au clavier et d'essayer tous ce qui passe par la tete.

    En tout cas merci, maintenant j'ai compris.

    Bonne continuation.

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. probleme AVEC delete
    Par norais dans le forum Langage
    R�ponses: 1
    Dernier message: 28/08/2012, 00h35
  2. Probleme avec "delete en ADO
    Par nguhv dans le forum VB 6 et ant�rieur
    R�ponses: 3
    Dernier message: 10/04/2007, 08h26
  3. Probleme avec delete[]
    Par anisjemmali dans le forum C++
    R�ponses: 4
    Dernier message: 28/03/2007, 17h46
  4. Probleme avec delete
    Par edogawa dans le forum Hibernate
    R�ponses: 4
    Dernier message: 04/09/2006, 14h39
  5. [ EJB ] [JBoss ] [ XDoclet ] probleme avec cascade-delete
    Par Houbbba dans le forum Wildfly/JBoss
    R�ponses: 4
    Dernier message: 03/05/2006, 10h05

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