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 pointeur


Sujet :

C++

  1. #21
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 613
    Points : 30 616
    Points
    30 616
    Par défaut
    il faut comprendre que l'adresse à laquelle va se trouver un objet que tu crées avec new va exclusivement dépendre des disponibilités du système, entre autres, au niveau de l'espace contigu dont il faut disposer en mémoire pour y placer l'ensemble des données.

    Bien sur, si tu viens d'indiquer au système qu'un espace X peut etre considéré comme disponible, il y a des chances, si tu demande au système de te fourni un espace mémoire identique, pour qu'il te renvoie l'espace mémoire que tu viens juste d'indiquer comme dispo, tout comme il y a cependant exactement le même nombre de chance pour qu'il t'envoie un espace mémoire contigu suffisant à n'importe quelle autre adresse.

    Il ne faut donc en aucun cas considérer, si tu écris un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
        Type *ptr = new Type;
        /* ... */
        delete ptr;
        Type * other = new type;
    }
    que ptr et other contiendront la même adresse mémoire...

    Au mieux, avec beaucoup de chance, ce n'est qu'une particularité d'un compilateur particulier, qu'une liberté prise par celui-ci pour éviter d'avoir à relancer le processus, malgré tout relativement couteux, d'une allocation dynamique par le système.

    Tu prendrais donc un énorme risque à considérer ce comportement comme "normal"
    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

  2. #22
    Nouveau membre du Club
    Inscrit en
    Juin 2011
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Juin 2011
    Messages : 45
    Points : 36
    Points
    36
    Par défaut
    Rien ne me choque dans tout cela(il en faut plus ...), j'essaye juste de comprendre la logique, je prend conscience que tout ça n'est pas très rigoureux mais ça permet de mieux comprendre ce qui se passe dans la machine .. Je crois avoir compris (commentaire dans le code):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        Objet *adr;
        Objet *bdr;
        adr=new Objet();
        bdr=new Objet();
     
        delete bdr;
        delete adr;
     
        bdr=new Objet(); //aloue une adresse à "bdr" qui est "par hasard" la même que "adr" (mais le hasard se produit à chaque fois... )
     
        adr->fonction(); // le fait qu'un objet ait été aloué à l'ancienne adresse pointé par "adr" fait que adr, qui possèdent toujours la valeur  l'adresse initial, peut être utilisé.

    Par contre si on code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        Objet *adr;
        Objet *bdr;
        adr=new Objet();
        bdr=new Objet();
     
        delete bdr;
        delete adr;
        adr=NULL; //"efface" la valeur de l'adresse dans "adr"
     
        bdr=new Objet(); //aloue une adresse à "bdr" qui est "par hasard" (mais le hasard se produit à chaque fois) la même que l'ancienne "adr"
     
        adr->fonction(); // ne marche plus car adr ne contient plus d'adresse

    Je m'interroge juste sur ce hasard qui se produit à chaque qui affecte la même adresse. Cela se produira-t-il vraiment à chaque fois si on fait le new juste après le delete ?

    Edit : koala01 a répondu à mes interrogations. Merci beaucoup, je me sens moins idiot maintenant !!!!

  3. #23
    Membre éprouvé

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Points : 1 086
    Points
    1 086
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Pourquoi? Normalement ca sort immediatement du scope.
    Pas compris... qu'est-ce qui sort du scope ?

    @vinceouille
    Il ne faut pas y voir du "hasard".
    Peut-être que dans ce contexte précis le gestionnaire de mémoire décide de gérer le tas comme une pile LIFO...

  4. #24
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Pour ce qui est d'obtenir une erreur quand on pointe sur un objet détruit, il existe une façon qui devrait être plus reproductible qu'un simple "je delete et j'espère que la page mémoire a été rendue": Les redéfinitions de fonctions virtuelles pures
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #25
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par cob59 Voir le message
    Pas compris... qu'est-ce qui sort du scope ?
    La variable que tu veux mettre a NULL. C'est aussi sense que de remettre a 0 des variables entieres apres les avoir utilisees.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  6. #26
    Nouveau membre du Club
    Inscrit en
    Juin 2011
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Juin 2011
    Messages : 45
    Points : 36
    Points
    36
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    La variable que tu veux mettre a NULL. C'est aussi sense que de remettre a 0 des variables entieres apres les avoir utilisees.
    Peut être que cela permet de ce prémunir d'appel à partir de pointeur non valide (et donc d'une erreur) en utilisant "if (ptr!=NULL) " avant l'appel.

  7. #27
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Là n'est pas la question: La question est pourquoi faire ça à la fin du bloc qui contient leur déclaration.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #28
    Nouveau membre du Club
    Inscrit en
    Juin 2011
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Juin 2011
    Messages : 45
    Points : 36
    Points
    36
    Par défaut
    Ok, d'accord avec toi, si le pointeur est définis dans le bloc OK. Mais dans le cas d'un pointeur définis et utilisé ailleurs c'est quand même utile ...

  9. #29
    Membre éprouvé

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Points : 1 086
    Points
    1 086
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Là n'est pas la question: La question est pourquoi faire ça à la fin du bloc qui contient leur déclaration.
    Je ne crois pas qu'il ait précisé où débutait ni où finissait son scope dans ses exemples de code. Apparemment il continue d'utiliser adr et bdr après leur delete, donc il me semble préférable de les mettre à NULL, pour que l'appel de adr->fonction(); fasse ce qu'il est censé faire : planter.

  10. #30
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par vinceouille Voir le message
    Ok, d'accord avec toi, si le pointeur est définis dans le bloc OK. Mais dans le cas d'un pointeur définis et utilisé ailleurs c'est quand même utile ...
    Les delete, c'est quand meme rare, c'est souvent gere par des classes faites pour ca (voir smart pointer). Meme sans les utiliser, dans la plupart des cas, on est en fin de vie de l'objet et assigner NULL ne sert a rien. Dans la plupart des cas restant, on va assigner tres rapidement un pointeur valide vers un autre objet. Les cas ou assigner NULL est sense existent, mais sont rares. Suffisemment rare pour qu'en faire une pratique systematique me semble tenir d'un culte du cargo.

    Citation Envoyé par cob59 Voir le message
    Je ne crois pas qu'il ait précisé où débutait ni où finissait son scope dans ses exemples de code. Apparemment il continue d'utiliser adr et bdr après leur delete, donc il me semble préférable de les mettre à NULL, pour que l'appel de adr->fonction(); fasse ce qu'il est censé faire : planter.
    Il fait des essais pour chercher a comprendre (ce qui peut aider, mais il faut faire attention a faire la part de hasard, de specifique a l'implementation et de garanti, ce qui n'est pas facile), c'est le genre de contextes ou les conseils de style ne sont pas particulierement pertinents.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  11. #31
    Membre éprouvé

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Points : 1 086
    Points
    1 086
    Par défaut
    Ce n'est pas qu'un conseil de style, puisqu'on facilite le debug en transformant un comportement indéterminé (déréférencement d'un pointeur désalloué) en un plantage pur et simple.

    Après, que cette situation soit occasionnelle ou non, ce n'est pas la question ; je n'ai rien voulu généraliser.

  12. #32
    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 vinceouille
    Edit : koala01 a répondu à mes interrogations. Merci beaucoup, je me sens moins idiot maintenant !!!!
    Pour finir de se convaincre, une preuve supplémentaire, avec du code, que se reposer sur ce comportement est dangereux :

    (windows 7, visual studio 2012)

    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
     
    #include <iostream>
    #include <string>
     
    struct Objet
    {
       std::string toto;
    };
     
    int main()
    {
       Objet *adr;
       Objet *bdr;
       int i = 0;
       while(1)
       {
          adr=new Objet();
     
          delete adr;
     
          bdr=new Objet();
     
          if(adr != bdr)
             break;
     
          delete bdr;
          i++;
    }
     
       std::cout << "numero iteration " << i << std::endl;
       std::cout << adr << std::endl;
       std::cout << bdr << std::endl;
       system("PAUSE");
    }
    Ce code affiche :

    numero iteration 2046
    000B8258
    000B9C58
    Press any key to continue . . .
    Paf, 2045 fois durant bdr s'est retrouvé à la même adresse que adr comme tu l'as observé, sauf que manque de bol à la 2046ème fois, les adresses sont différentes !
    Pourquoi 2046 , va savoir ! 2046, c'est très proche de 2048, qui ressemble a une limite classique qu'on rencontre souvent en informatique. Peut être que l'allocateur maintient en interne une sorte de liste de taille max 2048 et une fois la limite atteinte change de stratégie ? Ou peut être pas du tout, on ne sait pas, l'allocateur est une boite noire...

    il faut aussi noter que chez moi ce même code lancé depuis visual studio avec le debuggeur attaché (F5) semble rester indéfiniment dans le while, donc bdr se retrouve toujours à la même adresse que adr. Il faut le lancer sans le debuggeur (ctrl+F5) pour voir le comportement que j'ai montré plus haut. Donc là aussi on constate que le comportement de l'allocateur peut changer d'une manière assez imprévisible, en fonction d'un paramètre extérieur qui semble à première vue ne rien à voir avec tout ça.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 5
    Dernier message: 11/06/2008, 23h52
  2. [delete] detruire un pointeur
    Par poukill dans le forum C++
    Réponses: 2
    Dernier message: 09/03/2007, 10h05
  3. delete [] et pointeur intelligent
    Par zenux dans le forum C++
    Réponses: 11
    Dernier message: 04/12/2006, 09h18
  4. tableau de pointeurs et new, delete
    Par luckydigit dans le forum C++
    Réponses: 12
    Dernier message: 21/07/2006, 11h24
  5. [Pointeur]plusieurs new, un seul delete ?
    Par snoop dans le forum C++
    Réponses: 4
    Dernier message: 18/07/2006, 18h33

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