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 :

placement new sur tableau


Sujet :

C++

  1. #1
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut placement new sur tableau
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int i=une_valeur;
    void *pv=operator new(sizeof(UneClasse)*i);
    UneClasse *puc=new(pv) UneClasse [i];
    
    delete [] puc;//crash !!!
    Question simple ou complexe, je ne sais pas. Comment fait-on un delete d'un tableau construit par displacement new ?

    Faut-il faire explicitement comme ceci ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int i=une_valeur;
    void *pv=operator new(sizeof(UneClasse)*i);
    UneClasse *puc=new(pv) UneClasse [i];
     
    for (int x=0;x<i;++x)
     (&puc[x])->~UneClasse();
    operator delete(pv);
    Merci.

    EDIT: en fait même la deuxième écriture crash. Ceci semble fonctionner:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int i=une_valeur;
    void *pv=operator new(sizeof(UneClasse)*i);
     
    int x;
    UneClasse *puc=reinterpret_cast<UneClasse *>(pv);
    for (x=0;x<i;++x)
     new(&puc[x]) UneClasse;
     
    for (x=0;x<i;++x)
     (&puc[x])->~UneClasse();
    operator delete(pv);

  2. #2
    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
    Je pense que oui.
    Sauf que tu dois pouvoir simplifier cette ligne:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    (&puc[x])->~UneClasse();
    En ceci:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    puc[x].~UneClasse();
    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.

  3. #3
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    (placement new)

    MAT.

  4. #4
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    J'ai mis en gras la ligne litigieuse dans le premier post. Il semble qu'elle soit problématique car le pointeur pv ne pointe pas sur une zone mémoire de taille suffisante, sizeof(UneClasse)*i étant "trop petit".

    Personne n'utilise le placement new avec des tableaux ? Quels sont les règles pour allouer correctement suffisemment d'espace ? Commen libérer la mémoire à la fin de l'utilisation avec appel du destructeur pour chaque élément du tableau ?
    Merci.

    Un début de réponse ici, mais ce n'est pas très complet:
    http://www.cplusplus.com/reference/s...new%5B%5D.html

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Franchement, moi j'aurais tout simplement fait un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char* tab=new char[ta_taille];
    ...
    delete[] tab;
    Parce que ce new là, "non typé" ou "typé void", j'en ai jamais entendu parler. Par contre on aura tous compris que tu veux réserver x bytes de mémoire, et pour ça un new char[] est tout ce dont tu as besoin.

    J'aurais aussi fait une itération pour appeler les constructeurs au lieu d'utiliser cette syntaxe qu'encore une fois je ne connais pas. Avec une itération je suis sur que ça marchera par contre en devinant le fonctionnement de cet appel j'imagine des cas d'erreur.

  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
    Je me demande si ce n'est pas dû à un problème d'alignement. Quand je reprends ton exemple puc et pv n'ont pas la même adresse. Donc, t'as du déborder.

  7. #7
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par zais_ethael Voir le message
    ...
    delete[] tab;[/code]Parce que ce new là, "non typé" ou "typé void", j'en ai jamais entendu parler. Par contre on aura tous compris que tu veux réserver x bytes de mémoire, et pour ça un new char[] est tout ce dont tu as besoin.
    Comme tu ne sembles pas connaître le "placement new", je t'invite à lire ceci
    http://www.cplusplus.com/reference/s...new%5B%5D.html ainsi que les liens qui s'y trouve et concernant operator new [] et operator delete [].
    Je suis loin d'en connaître toutes les subtilités, raison de cette discussion d'ailleurs

    Et non je ne veux pas allouer x bytes en mémoire, je veux construire un tableau d'objets dans une zone mémoire existante. Puis le détruire.

    Donc la question est: comment utiliser les "placement new" avec les tableaux ?
    En principe les compilateurs doivent gérer implicitement chaque élément du tableau en appelant leur constructor lors du "placement new" et leur destructor lors du "placement delete". Mais ça ne fonctionne pas comme je le voudrais. Donc quels sont les régles en C++ pour savoir si on a alloué assez d'espace mémoire ?
    get_temporary_buffer et return_temporary_buffer sont-ils la réponse, est-ce standard ?

  8. #8
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Je me demande si ce n'est pas dû à un problème d'alignement. Quand je reprends ton exemple puc et pv n'ont pas la même adresse. Donc, t'as du déborder.
    En effet. Il semble que le compilateur se réserve un entier en plus de la taille nécessaire au tableau pour y mémoriser le nombre d'éléments car il faut bien qu'il connaisse ce nombre lors de la destruction du tableau.
    Mais bon, c'est un constat empirique. Quelle est la règle "standard" ?

  9. #9
    Membre averti Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Points : 323
    Points
    323
    Par défaut
    Bonjour,
    Sur minGW, l'exemple du premier post ne plante pas. Mais il est vrai que ça peu dépendre du compilateur.

    Pour être sur d'allouer de l'espace pour un tableau, essaie avec l'opérateur new sur les tableau:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void *pv = operator new[](sizeof(bidul) * i);

  10. #10
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Merci.
    Sous VC++6 ça ne compile pas. Et sous VS2005 ça ne change rien de mettre [] ou pas.
    De toute façon je ne parviens pas à trouver l'équivalent d'un "placement delete", c'est à dire demander au compilateur qu'il appelle implicitement les destructor sans désallouer la mémoire (l'opération inverse du "placement new"). J'en suis réduit à faire une boucle et appeler le destructor de chaque élément un par un.
    Bon, donc tant pis, j'en conclus qu'il n'y a pas de prise en charge standard du placement new pour les tableaux. Je ferais les boucles moi-même.

  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
    Au delà de la question de principe, on peut se poser la question de pourquoi tu as besoin de faire un placement new sur un tableau ? Je ne vois pas quel cas peut le nécessiter.
    Je me demandais si ton besoin ne peut être rempli par Boost.optional : tu crées un vecteur de boost.optional<MaClasse> que tu peux ensuite effectivement construire et détruire au besoin.

  12. #12
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Le placement new n'alloue pas la mémoire.

    J'aurais donc tendance à dire qu'il ne faut pas faire un delete dessus...

    Pour détruire tes objets :
    - appeler delete sur chacun des éléments de ton tableau
    - libérer la mémoire avec un delete pv (et pas un delete[], puisqu'il a été alloué avec new, et pas puc, puisqu'il n'a pas été alloué mais placé).

  13. #13
    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 white_tentacle Voir le message
    Le placement new n'alloue pas la mémoire.

    J'aurais donc tendance à dire qu'il ne faut pas faire un delete dessus...

    Pour détruire tes objets :
    - appeler delete sur chacun des éléments de ton tableau
    - libérer la mémoire avec un delete pv (et pas un delete[], puisqu'il a été alloué avec new, et pas puc, puisqu'il n'a pas été alloué mais placé).
    Ca revient à faire sa troisième solution du premier post. Si j'ai bien compris le bp, c'est de pouvoir automatiquement appeler le destucteur sur tous les éléments du tableau sans avoir à faire la boucle (comme pour le placement new). Mais, j'ai l'impression que ce n'est pas possible ; le delete appelant le destructeur puis détruisant la mémoire.

  14. #14
    Membre averti Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Points : 323
    Points
    323
    Par défaut
    Cela n'est pas toujours possible, mais une autre solution serai de surcharger les opérateur new et delete de la class, pour leur donner le comportement voulu. Ainsi un new[] et delete[] "normaux" suffiront.
    Une autre solution, (mais plus dangereuse) serai de ne surcharger que le delete, pour qu'il ne fasse rien.

Discussions similaires

  1. [ActionListener] Evénement sur tableau de boutons
    Par frouge dans le forum Composants
    Réponses: 5
    Dernier message: 08/10/2011, 02h44
  2. Bug Firefox sur tableau centré dans un div (mauvais refresh)
    Par FrankOVD dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 04/07/2005, 17h47
  3. loop sur tableau associatif
    Par Plawi dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 28/02/2005, 11h29
  4. placement dans un tableau
    Par ma_mat dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 17/11/2004, 14h48
  5. Réponses: 25
    Dernier message: 16/07/2003, 20h41

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