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 :

Différence entre delete et delete []


Sujet :

C++

  1. #1
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut Différence entre delete et delete []
    Bonjour

    On sait tous que quand on fait une allocation dynamique,
    Il faut désallouer avec delete [] et non delete. Alors moi, j'ai essayé en débug de voir ce qu'il se passe avec visual studio. J'ai tout d'abord linké le programme avec la version release de la CRT. Ensuite, j'ai fait ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int *o=new int[100];
    for(int j=0;j<100;j++)
    	o[j]=3;
    delete o;
    Ce qui est pas bon. Quand j'alloue le tableau de 100 int de valeur 3, je vois ceci:
    Nom : 1.JPG
Affichages : 145
Taille : 73,6 Ko
    On voit bien le tableau avec les 100 int. Ensuite, quand je fais le delete, je vois que tous les int sont désalloués. Moi, je m'attendais à ce que seule la première adresse, celle pointée par o soit désallouée.
    Une fois le delete executée, voila ce que je vois:
    Nom : 2.JPG
Affichages : 144
Taille : 69,1 Ko

    Ensuite, j'ai fait le truc correct:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int *o=new int[100];
    for(int j=0;j<100;j++)
    	o[j]=3;
     
    delete [] o;
    Et dans la première image, on voit l'allocation, et dans la deuxième, on voit la désallocation.

    Nom : 3.JPG
Affichages : 130
Taille : 87,3 Ko


    Nom : 4.JPG
Affichages : 133
Taille : 78,0 Ko

    On voit qu'il n'y a aucune différence. Je ne comprends pas. Comment faire pour voir la différence entre delete et delete[] ?

    Merci

  2. #2
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Hello

    A mon avis, c'est juste une optimisation qui détecte ton erreur et la corrige.
    Find me on github

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2011
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2011
    Messages : 59
    Points : 120
    Points
    120
    Par défaut
    salut ,

    sur un type simple (ADT) tu ne verras pas la différence, car dans les deux cas ça ne fait que libéréer la mémoire allouée

    par contre sur un type avec constructeur/destructeur là il y a différence

    dans delete : seul le premier destructeur est appelé ensuite la mémoire est libérée

    dans delete[] : les destructeurs sont appelée et la mémoire libérée

    Cdt

  4. #4
    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
    détail d'implémentation du compilateur. Cela n'a que peu de sens de regarder.
    Tu invoques un comportement non défini. Donc le compilateur peut faire comme si de rien était, générer une exception, planter ou faire le café. Je ne vois vraiment pas l'intérêt de cette question

  5. #5
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    sur un type simple (ADT) tu ne verras pas la différence, car dans les deux cas ça ne fait que libéréer la mémoire allouée
    J'ai testé avec une classe contenant un int et un double. Pas vu de différence entre delete et delete [].

    Tu invoques un comportement non défini. Donc le compilateur peut faire comme si de rien était, générer une exception, planter ou faire le café. Je ne vois vraiment pas l'intérêt de cette question
    Hé oui, mais c'est bien facile de dire que l'on provoque une exception, on dit ce que raconte la norme.
    Encore faut il le démontrer et/ou l'expérimenter. C'est comme ca que je comprends.

  6. #6
    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 deubelte Voir le message
    Hé oui, mais c'est bien facile de dire que l'on provoque une exception, on dit ce que raconte la norme.
    Encore faut il le démontrer et/ou l'expérimenter. C'est comme ca que je comprends.
    J'ai pas dit que ça provoque une exception. J'ai dit que tu évoques un comportement indéterminé (l'exception pouvant être une réponse comme une autre). Pour le reformuler autrement, tu écris un code faux et buggé et tu regardes comment ça marche ... au cas où quoi ? Au cas où ça tomberait en marche ? Et quelle(s) serai(en)t ta(tes) conclusion(s) alors ?? Aucune car tu invoques un comportement indéterminé. Tu ne peux donc rien conclure sur ce comportement.

  7. #7
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    J'ai pas dit que ça provoque une exception. J'ai dit que tu évoques un comportement indéterminé (l'exception pouvant être une réponse comme une autre).
    Peux tu me donner un cas où ca renverrait une exception? Enfin, un truc qui plante?

    Merci

  8. #8
    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 kessoufi Voir le message
    salut ,

    sur un type simple (ADT) tu ne verras pas la différence, car dans les deux cas ça ne fait que libéréer la mémoire allouée
    ADT, pour moi c'est Abstract Data Type. Peut-être pensais-tu à POD (Plain Old Data) ? En fait, dans l'implémentation de Microsoft Visual C++ 2010 en mode débug et avec les options de compilations (XXX) cela a plus à voir avec la nécessité ou non d'appeler un constructeur ou un destructeur. (la présence d'un destructeur rend en C++98 un type non POD mais pas la seule présence d'un constructeur).
    Pour reprendre, new/new[] fait deux choses : allouer un espace mémoire suffisant et appeler le constructeur qu'il faut. delete/delete[] à l'inverse appelle les destructeurs nécessaires et libère la mémoire.
    Un new int[]/delete [] ou un new int[]/delete semblent identique car j'imagine que l'implémentation la plus facile pour un compilateur est d'appeler juste la fonction d'allocation et de libération de la mémoire. MAIS CA RESTE UN COMPORTEMENT INDETERMINE

  9. #9
    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 deubelte Voir le message
    Peux tu me donner un cas où ca renverrait une exception?
    Bon une exception non car un delete ne devrait pas en générer.
    Citation Envoyé par deubelte Voir le message
    Enfin, un truc qui plante?

    Merci
    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
    #include <memory>
     
    void *operator new[](std::size_t) throw(std::bad_alloc)
    {
        static int my_buffer[100];
        return &my_buffer[0];
    }
     
    void operator delete[](void *ptr) throw()
    {}
     
    #include <iostream>
    int main()
    {
        int *p = new int[0];
        delete []p; // ok
     
        int *q = new int[0];
        delete p; // plantage
     
     
    std::cout<<"bye\n";
        return 0;
    }
    Ceci dit, tu invoques un comportement indéterminé. Quelles conclusions tu peux en tirer ??? J'aimerais bien comprendre

  10. #10
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    Yo,
    j'ai essayé un nouveau truc, avec cette classe non POD.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class  S{
    public:
    	S(){};
    	S(int y,std::string d):o(y),e(d){};
     private:
    	int o;
    	std::string e; 
    };
    quand je fais ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    S* o=new S[100];
    for(int j=0;j<100;j++)
    	o[j]=S(1,"ee");
    delete [] o;
    ça marche, alors si je fais delete o;

    ca me renvoie comme erreur:

    Windows has triggered a breakpoint in cac.exe.

    This may be due to a corruption of the heap, which indicates a bug in cac.exe or any of the DLLs it has loaded.

    This may also be due to the user pressing F12 while cac.exe has focus.

    The output window may have more diagnostic information.

  11. #11
    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 deubelte Voir le message
    ...



    Et moi, et moi, quand je fais ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main()
    {
     int bug = 0;
     bug = 1/bug;
    return 0;
    }
    Ben j'ai un bug (ou pas car là aussi c'est un comportement indéterminé)

  12. #12
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2011
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2011
    Messages : 59
    Points : 120
    Points
    120
    Par défaut
    ça me fait pareil avec cette classe ( ça déclenche un breakpoint) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    struct a
    {
        int i;
        ~a() {}
    };
    mais lorsque je commente le destructeur ça passe (comme pour un int*), et pourtant ce n'est pas du POD,

  13. #13
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    oui, mais il fallait le savoir que en mettant que des integrales, ca marche, alors que quand on mets des string, ca renvoie une erreur!!

  14. #14
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    mais lorsque je commente le destructeur ça passe (comme pour un int*), et pourtant ce n'est pas du POD,
    idem pour moi. Alors ca c'est marrant. Pourquoi quand on déclare un destructeur, ca marche pas, alors que quand on le déclare, ca marche??

  15. #15
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2011
    Messages : 576
    Points : 1 528
    Points
    1 528
    Par défaut
    Il n'y a pas de raison. Comme l'a dit 3DArchi, tu utilise un fonctionnalité à un endroit où tu n'es pas censé l'utilisé. Si ça marche, c'est grâce à l'opération du saint esprit. Et ce n'est pas dit que ça remarchera une autre fois.
    La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer. - Antoine de Saint-Exupéry

  16. #16
    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 pyros Voir le message
    Il n'y a pas de raison. Comme l'a dit 3DArchi, tu utilise un fonctionnalité à un endroit où tu n'es pas censé l'utilisé. Si ça marche, c'est grâce à l'opération du saint esprit. Et ce n'est pas dit que ça remarchera une autre fois.
    +100000

  17. #17
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Citation Envoyé par deubelte Voir le message
    oui, mais il fallait le savoir que en mettant que des integrales, ca marche, alors que quand on mets des string, ca renvoie une erreur!!

    uh? C'est un comportement indéterminé... cherche pas, fait le sur un autre pc, un autre jour, à la pleine lune, etc et sa sera pas pareil. C'est le propre même d'un comportement indéterminé... tu te poses des questions réellement inutile là, y'a des choses bien plus intéressantes à comprendre et à apparendre.
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  18. #18
    screetch
    Invité(e)
    Par défaut
    pour répondre a ta question, lorsque delete[] est forcé d'appeler des destructeurs, new[] ajoute 4 octets (pit-être 8 en 64 bits ) avant les objets et y met le nombre d'objet.

    delete[] lit alors ce qui se trouve avant les objets, appelle X fois le destructeur, et libère en appelant free(array-4)
    delete (sans le []) appelle le destructeur une fois, et ensuite appèle free(array) => d'où un crash puisque ce n'est pas le début du bloc mémoire.

    si il n'y a pas de destructeur a appeler, new[] n'ajoute pas le nombre d'objet et delete[] ne fait que liberer la mémoire, ce qui est le même comportement que delete sans [].

    MAIS ca c'est un détail d'implémentation, si c'est différent sur un autre compilo personne n'ira regarder. C'est grossièrement valable sur GCC et visual studio, sans doute partout mais aucune garantie.

  19. #19
    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,

    Il faut surtout comprendre que l'appel de delete (respectivement delete[] ) sur quelque chose créé par new[] (respectivement new) provoque un comportement indéterminé (selon la norme)!!!

    A partir de là, et quoi que puisse te dire ton compilateur, il s'agit de prendre toutes les dispositions pour éviter d'en arriver à un tel état de fait, à savoir:
    • invoquer impérativement delete[] sur quelque chose créé par new[]
    • invoquer impérativement delete sur quelqeu chose créé par new
    N'oublie pas, non plus, que l'existence des différentes collections (tant issues du standard que celles rajoutées par boost) et des pointeurs intelligents devraient le plus souvent te permettre d'éviter le recours à delete[]
    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

  20. #20
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    En fait, je me suis posé cette question, car dans le livre de Sutter, exceptionnal C++, page 144, on a:

    Consider the following code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class B
    {
    virtual ~B();
    void operator delete (void*,size_t) throw();
    void operator[] delete (void*,size_t) throw();
    void f(void*,size_t) throw();
    };
    class D: public B
    {
    public:
    void operator delete (void*)throw();
    void operator delete[] (void*)throw();
    };
    Or, dans le livre de Scott Meyers, il nous dit qu'il ne faut jamais traiter des tableau de manière polymorphe.
    (Never treat array polymorphically). mais dans le code ci-dessus, cela laisse penser qu'on va utiliser des tableaux d'objets dérivés.

    Il y a comme un petit problème, ou du moins, une incohérence dans la question de Sutter.

Discussions similaires

  1. Différence entre TRUNCATE et DELETE ?
    Par HRS dans le forum SQL
    Réponses: 18
    Dernier message: 12/08/2011, 16h07
  2. différence entre delete et delete[]
    Par deubelte dans le forum C++
    Réponses: 7
    Dernier message: 25/02/2009, 03h30
  3. [BDE][TTABLE] différence entre EMPTY et DELETE
    Par cal dans le forum Bases de données
    Réponses: 1
    Dernier message: 15/02/2008, 08h04
  4. Différences entre delete table et delete from table
    Par pegase06 dans le forum Administration
    Réponses: 3
    Dernier message: 16/02/2007, 15h25
  5. Réponses: 3
    Dernier message: 07/05/2002, 16h06

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