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 :

question sur new et delete


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    905
    Détails du profil
    Informations personnelles :
    Localisation : France, Vienne (Poitou Charente)

    Informations forums :
    Inscription : Mai 2011
    Messages : 905
    Points : 85
    Points
    85
    Par défaut question sur new et delete
    Bonjour,

    J'aurais besoin de savoir une chose ,
    Quel problème ou phénomène peux t'il se produire si on alloue avec un 'new' : un pointer (enregistrement) et qu'on le libère avec la fonction 'free' ? ???

    et pour inverse ('malloc' et 'delete') ??

    Merci

  2. #2
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    Bonjour,

    L'implosion de l'Univers ...

    En fait c'est très simple, c'est un comportement indéfini, donc tu vas avoir des résultats différents selon l'implémentation (donc la bibliothèque, le compilo, le système). Mais dans 99% des cas tu vas simplement corrompre ta mémoire et faire crasher bêtement ton programme.

  3. #3
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Ce n'est pas indéfini du tout.

    malloc/free gèrent un bloc de mémoire, tandis que new et delete gèrent un pointeur typé.
    new et delete sont garanti d'appeler respectivement le constructeur et le destructeur, tandis que malloc et free ne le font pas.

    Dans l'absolu, l'appel réellement fait par delete bidule serait bidule->~Bidule(); free(bidule);. Mais un retour à la norme est de rigueur pour les détails.

    La conséquence de free(new fstream("fichier"));, c'est que le fichier ne sera pas fermé, parce que son destructeur ne sera pas appelé.


    Pour malloc delete, c'est plus pervers, parce que tu détruiras un objet non construit.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2011
    Messages
    905
    Détails du profil
    Informations personnelles :
    Localisation : France, Vienne (Poitou Charente)

    Informations forums :
    Inscription : Mai 2011
    Messages : 905
    Points : 85
    Points
    85
    Par défaut
    ok,
    en tout cas pour les classes , il faut passer par new.

  5. #5
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    Citation Envoyé par leternel Voir le message
    Ce n'est pas indéfini du tout.
    Si ça l'est.
    Tu ne sais pas si, et où, malloc() et free stockent des informations complémentaires. Chaque compilateur est libre de les implémenter comme il veut. Tu sais peut-être ce que font malloc()/free() et new/delete, en revanche il n'y a aucune information dans les standards par rapport au comportement du programme lorsqu'on fait un mix des deux.

    en tout cas pour les classes , il faut passer par new.
    Dans tous les cas en C++ il faut se passer de malloc() et free(). Et si possible ne pas manipuler les pointeurs directement, passer par des classes conçues pour ça (genre les classes de smart pointers). Bien sûr tout dépend après du projet.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par the Hound Voir le message
    Si ça l'est.
    Tu ne sais pas si, et où, malloc() et free stockent des informations complémentaires. Chaque compilateur est libre de les implémenter comme il veut. Tu sais peut-être ce que font malloc()/free() et new/delete, en revanche il n'y a aucune information dans les standards par rapport au comportement du programme lorsqu'on fait un mix des deux.



    Dans tous les cas en C++ il faut se passer de malloc() et free(). Et si possible ne pas manipuler les pointeurs directement, passer par des classes conçues pour ça (genre les classes de smart pointers). Bien sûr tout dépend après du projet.
    En fait, vous avez tous les deux presque raison, mais plus ou moins tord...

    Ce qui provoque un comportement indéterminé, c'est le fait que le constructeur ou que le destructeur ne soit jamais appelé. Par contre, on sait que malloc n'appellera jamais le constructeur et que free n'appellera jamais le destructeur. On peut donc très clairement déterminer ce qui se passe si on fait un mix de new + free ou de malloc + delete: le constructeur ou le destructeur ne sera pas appelé en fonction de ce que l'on a fait.

    Après, il se fait que ces deux circonstances auront pour résultat de provoquer un comportement indéfini, mais on est à ce niveau déjà "une étape plus loin"
    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

  7. #7
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Merci Koala01
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  8. #8
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,En fait, vous avez tous les deux presque raison, mais plus ou moins tord...

    Ce qui provoque un comportement indéterminé, c'est le fait que le constructeur ou que le destructeur ne soit jamais appelé. Par contre, on sait que malloc n'appellera jamais le constructeur et que free n'appellera jamais le destructeur. On peut donc très clairement déterminer ce qui se passe si on fait un mix de new + free ou de malloc + delete: le constructeur ou le destructeur ne sera pas appelé en fonction de ce que l'on a fait.

    Après, il se fait que ces deux circonstances auront pour résultat de provoquer un comportement indéfini, mais on est à ce niveau déjà "une étape plus loin"
    Vu de la norme, l'appel de delete sur un pointeur non obtenu par new est en lui-même un comportement indéfini, indépendamment des constructions/destructions :

    Otherwise, the behavior is undefined if the value supplied to operator delete(void*) in the standard library is not one of the values returned by a previous invocation of either operator new(std::size_t) or operator new(std::size_t, const std::nothrow_t&) in the standard library, and the behavior is undefined if the value supplied to operator delete[](void*) in the standard library is not one of the values returned by a previous invocation of either operator new[](std::size_t) or operator new[](std::size_t, const std::nothrow_t&) in the standard library.
    Il n'est donc pas même pas certain que dans un tel cas il y ait une tentative d'appel du destructeur, même si c'est un comportement possible voire probable.
    Une implémentation peut (et à titre personnel, j'apprécierais) fournir un mode debug où ces appels claquent dans une assertion fausse.

  9. #9
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par koala01 Voir le message
    On peut donc très clairement déterminer ce qui se passe si on fait un mix de new + free ou de malloc + delete: le constructeur ou le destructeur ne sera pas appelé en fonction de ce que l'on a fait.
    On peut tout à fait envisager une implémentation où new et malloc n'ont pas accès au même type de mémoire, et donc où appeler free sur un objet créé par new planterait méchamment.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  10. #10
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Ca, je n'en suis pas sûr, parce qu'il me semble que les segments mémoires sont décrits par la norme, et que les quatre fonctions s'occupent du même segment (heap)
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  11. #11
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Points : 1 211
    Points
    1 211
    Par défaut
    Citation Envoyé par leternel Voir le message
    Ca, je n'en suis pas sûr, parce qu'il me semble que les segments mémoires sont décrits par la norme, et que les quatre fonctions s'occupent du même segment (heap)
    Oui mais c'est pas parce qu'elles gèrent toutes le tas qu'elles sont "compatibles", ou du moins qu'on puisse résumer un new suivi d'un free() par "un objet alloué puis construit puis seulement libéré".
    Imagine (c'est un exemple) que new alloue X octets de plus d'en-tête pour stocker des métadonnées, octets utilisés ensuite par delete pour une raison ou une autre, et que malloc() crée lui aussi un en-tête mais avec des données qui n'ont rien à voir. Si tu new puis tu free(), cette dernière risque de planter à cause des métadonnées qui sont pas formatées comme elles le devraient (càd par malloc() et non new).
    Mais ça, on ne peut pas le savoir, parce que les compilos et bibliothèques décident de leur implémentation, et les standards (C et C++) ne disent rien à ce propos.
    Donc c'est un comportement indéfini.

    A mes yeux, dire que free() est l'équivalent d'un delete sans appel du destructeur, est faux.

  12. #12
    Membre éclairé
    Avatar de buggen25
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    554
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Août 2008
    Messages : 554
    Points : 709
    Points
    709
    Par défaut
    Mais pourquoi tu veux faire ça ?
    If you type Google into Google, you Can break the internet" - The IT Crowd

  13. #13
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Et pourtant, regarde comment s'utilise et s'implémente un placement new, tu verras que c'est a peu près ca.
    Pour être précis, je dis qu'un new est un malloc suivi d'un placement new.

    Comme je n'ai pas souvenir du placement delete, c'est une autre histoire.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  14. #14
    Membre éclairé
    Avatar de buggen25
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    554
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Août 2008
    Messages : 554
    Points : 709
    Points
    709
    Par défaut
    Citation Envoyé par leternel Voir le message
    Et pourtant, regarde comment s'utilise et s'implémente un placement new, tu verras que c'est a peu près ca.
    Pour être précis, je dis qu'un new est un malloc suivi d'un placement new.

    Comme je n'ai pas souvenir du placement delete, c'est une autre histoire.
    Oui mais le problème est que newalloue sur le "stock libre" (une zone mémoire) et que mallocalloue sur le "Tas" (une autre zone mémoire, c'est comme si on prenait deux livres semblables, et que l'un on le met sur l'étage du haut et que l'autre sur l'étage du bas d'une étagère, maintenant il se peut que les deux zones se trouvent dans le même endroit, cela dépend de l'implémentation, ce qui donnerait certainement des résultats catastrophiques.

    En plus de ça certaines fonctions ne sont pas accessible quand on alloue avec malloc(), c'est qu'il faut connaitre dès le départ la taille de l'objet, et que certaines fonctions ne sont pas accessibles tel que le constructeur et le destructeur, sans oublier le faire que malloc retourne un type void *.

    Maintenant si tu veux déclencher une troisième guerre mondiale.
    If you type Google into Google, you Can break the internet" - The IT Crowd

  15. #15
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par leternel Voir le message
    Et pourtant, regarde comment s'utilise et s'implémente un placement new, tu verras que c'est a peu près ca.
    Pour être précis, je dis qu'un new est un malloc suivi d'un placement new.
    Conceptuellement, ce n'est pas totalement faux. Mais ce n'est pas vrai non plus
    Tu peux dire plus précisément qu'un new, c'est une allocation de mémoire brute, suivi d'un placement new. Et qu'un delete correspond à l'appel explicite du destructeur suivi d'une désallocation de mémoire à l'aide d'une fonction compatible avec celle utilisée pour l'allocation.

    Si à la main tu fais malloc + placement new, tu devras faire destructeur explicite + free.
    Mais si tu fais new, tu n'auras pas le droit de faire destructeur explicite + free, tu devras faire delete.



    Citation Envoyé par leternel Voir le message
    Comme je n'ai pas souvenir du placement delete, c'est une autre histoire.
    12.4/13 : appel explicite du destructeur.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  16. #16
    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 519
    Points
    41 519
    Par défaut
    Et ça devient encore plus compliqué quand on rajouter new[]/delete[] dans l'équation, car new[] doit forcément stocker quelque part le nombre d'objets alloués.
    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.

Discussions similaires

  1. Question sur "new" et les tableaux
    Par Pandi_Panda dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 27/05/2012, 12h42
  2. Petite question sur 'new'
    Par yvancoyaud dans le forum Flex
    Réponses: 5
    Dernier message: 21/05/2012, 12h09
  3. Question sur new
    Par deubelte dans le forum C++
    Réponses: 4
    Dernier message: 19/05/2011, 14h06
  4. Question sur l'éternel delete de Java :-)
    Par threshold dans le forum Entrée/Sortie
    Réponses: 10
    Dernier message: 02/01/2008, 17h42
  5. Segmentation fault sur new[] et delete[]
    Par Don ViP dans le forum C++
    Réponses: 4
    Dernier message: 30/04/2006, 00h29

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