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

Langage C++ Discussion :

new et exception constructeur : que dit la norme pour la désallocation ?


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut new et exception constructeur : que dit la norme pour la désallocation ?
    Bonjour,

    Imaginons que je possède le code suivant :
    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 <iostream>
     
    class Foo{
         public : 
              Foo(void){ throw int(0); }
     
    }
     
    int main(void)
    {
          Foo * ptr = nullptr;
          try {
                ptr = new Foo;
         } catch (int)
         {
                std::cout << ptr << std::endl;
         }
    }
    new va allouer l'espace mémoire puis il va l'initialisé en appelant le constructeur de Foo.
    Mais ce dernier va lancer une exception, je vais donc entrer dans le catch, ptr valant toujours nullptr.

    Il me semblerait logique que new ai lui-même désalloué l'espace qu'il a alloué sinon on risquerait d'avoir des fuites de mémoires.
    Mais que dit exactement la norme à ce sujet ?

    Si j'utilise ensuite un new [], et qu'un seul des constructeur échoue, ce serait dommage qu'il désalloue tout l'espace mémoire et qu'il détruise les objets déjà construits.
    Mais d'un autre côté, comme on a une exception, on ne peux pas récupérer de pointeurs et on se retrouverait dans le cas précédant avec une fuite mémoire.

    Je vois ce que le compilateur doit faire, mais j'aimerais savoir ce qu'en pense la norme.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Si une exception est lancée, ton programme s'arrête (enfin moi s'est le cas) donc obligation de libérer toute la mémoire, sinon, tu auras des fuites de mémoire.

    new [] instancie juste un tableau, mais en aucun cas les éléments de ton tableau, si tu veux tester si un élément de ton tableau à bien été alloué, tu dois faire le test un par un pour chaque élément de ton tableau.

    Tu peux toujours, si tu souhaite que le tableau soit libéré dans n'importe quel cas, utiliser quelque chose comme ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    int main(void)
    {
          std::unique_ptr<Foo[taille]> ptr;
         try {
               ptr = std::make_unique<Foo[taille]>();
         } catch (int)
         {
                std::cout << ptr << std::endl;
         }
    }

    Si j'ai bien compris la norme.

  3. #3
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Citation Envoyé par Lolilolight Voir le message
    Si une exception est lancée, ton programme s'arrête (enfin moi s'est le cas)
    Heu... non vu que je fais un catch...

    new [] instancie juste un tableau, mais en aucun cas les éléments de ton tableau
    new[] appelle le constructeur par défaut pour chaque élément du tableau.

    si tu veux tester si un élément de ton tableau à bien été alloué, tu dois faire le test un par un pour chaque élément de ton tableau.

    new[] alloue un seul bloc contiguë en mémoire, l'allocation se fait en une seule fois et échoue ou réussie.
    Soit tout le tableau est alloué, soit il ne l'est pas.

    Tu peux toujours, si tu souhaite que le tableau soit libéré dans n'importe quel cas, utiliser quelque chose comme ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    int main(void)
    {
          std::unique_ptr<Foo[taille]> ptr;
         try {
               ptr = std::make_unique<Foo[taille]>();
         } catch (int)
         {
                std::cout << ptr << std::endl;
         }
    }
    Totalement HS ici.

  4. #4
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Pour moi la question ne se pose pas vraiment, si new échoue, ptr n'est pas modifié donc, tu ne peux pas faire de delete toi-même dessus.

    Sinon, voici une piste sur Can I throw an exception from a constructor? From a destructor? :
    You should throw an exception from a constructor whenever you cannot properly initialize (construct) an object. There is no really satisfactory alternative to exiting a constructor by a throw.

  5. #5
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    Pour moi la question ne se pose pas vraiment, si new échoue, ptr n'est pas modifié donc, tu ne peux pas faire de delete toi-même dessus.
    Oui, c'est ce que j'ai dit dans mon premier post.

    Je veux juste savoir ce que dit la norme à ce sujet.

    ?
    Je ne comprend pas pourquoi tu me montre ce lien.

  6. #6
    Candidat au Club
    Inscrit en
    Janvier 2014
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Janvier 2014
    Messages : 5
    Par défaut
    Oui, new[] va tout supprimer

    Une solution est de faire un allocation sans appel de constructeur (par exemple avec malloc) puis de faire un placement new pour appeler le constructeur sur chaque élément. Regarde les sources de vector, je crois qu'il fait comme ça. Par contre, c'est une technique bas niveau et peu sécurisée, à encapsuler dans un classe RAII

  7. #7
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Citation Envoyé par Blainey Voir le message
    Oui, new[] va tout supprimer

    Une solution est de faire un allocation sans appel de constructeur (par exemple avec malloc) puis de faire un placement new pour appeler le constructeur sur chaque élément. Regarde les sources de vector, je crois qu'il fait comme ça. Par contre, c'est une technique bas niveau et peu sécurisée, à encapsuler dans un classe RAII
    Donc ensuite pour libérer, j'appelle explicitement le constructeur puis je libère avec free() ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Foo * myTab = malloc(...);
    for(...)
          new(myTab + i) Foo;
    //...
    for(...)
          myTab[i].~Foo();
    free(myTab);
    Très intéressante comme idée. .

    Je vais essayer de mon plonger dans la norme pour la première partie de ma question .

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. designer VS2008 exception alors que build fonctionne
    Par Golzinne dans le forum Silverlight
    Réponses: 2
    Dernier message: 01/09/2010, 16h37
  2. Cumuler 2 emplois : que dit la loi?
    Par Baldy dans le forum Droit du travail
    Réponses: 10
    Dernier message: 28/08/2010, 12h59
  3. Réponses: 8
    Dernier message: 13/05/2009, 18h18
  4. Réponses: 2
    Dernier message: 13/06/2008, 16h34
  5. [C#]Comment eviter Exception pendant que programme en pause?
    Par Revan012 dans le forum Windows Forms
    Réponses: 11
    Dernier message: 11/03/2006, 03h05

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