Maison >développement back-end >C++ >Le placement est-il nouveau pour les tableaux vraiment portables en C ?

Le placement est-il nouveau pour les tableaux vraiment portables en C ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-11-15 04:05:02622parcourir

Is Placement New for Arrays Truly Portable in C  ?

Placement nouveau pour les tableaux : problèmes de portabilité

En C, le placement nouveau permet l'allocation de mémoire à une adresse spécifiée. Cependant, son utilisation pour les baies présente des problèmes de portabilité. Cet article explore le problème et présente une solution portable.

On suppose souvent que le pointeur renvoyé par new[] coïncide avec l'adresse fournie. Cependant, la norme C (5.3.4, note 12) indique que cela pourrait ne pas être le cas. Cela pose un problème lors de la tentative d'allocation d'un tampon pour un tableau à l'aide du placement new.

Le code suivant illustre ce problème :

#include <new>
#include <stdio.h>

class A {
public:
    A() : data(0) {}
    virtual ~A() {}
    int data;
};

int main() {
    const int NUMELEMENTS = 20;

    char* pBuffer = new char[NUMELEMENTS * sizeof(A)];
    A* pA = new(pBuffer) A[NUMELEMENTS];

    printf("Buffer address: %x, Array address: %x\n", pBuffer, pA);

    delete[] pBuffer; // Assertion failure due to heap corruption

    return 0;
}

L'examen de la mémoire révèle que certains compilateurs (par exemple, Visual Studio) alloue des octets supplémentaires avant le tableau pour la comptabilité interne (par exemple, le nombre d'éléments du tableau). Cela peut conduire à une corruption du tas.

La question se pose : pouvons-nous déterminer la surcharge associée au placement de nouveaux tableaux pour différents compilateurs ? L'objectif est de trouver une solution portable.

Solution proposée

Plutôt que d'utiliser le placement new sur l'ensemble du tableau, une solution de contournement possible consiste à allouer chaque élément du tableau individuellement :

int main(int argc, char* argv[]) {
  const int NUMELEMENTS = 20;

  char* pBuffer = new char[NUMELEMENTS * sizeof(A)];
  A* pA = (A*)pBuffer;

  for (int i = 0; i < NUMELEMENTS; ++i) {
    pA[i] = new(pA + i) A();
  }

  printf("Buffer address: %x, Array address: %x\n", pBuffer, pA);

  // Manual destruction
  for (int i = 0; i < NUMELEMENTS; ++i) {
    pA[i].~A();
  }

  delete[] pBuffer;

  return 0;
}

Cette méthode contrôle explicitement le placement de chaque objet dans le tableau et garantit que la destruction est effectuée correctement.

Conclusion

L'utilisation du placement new pour les tableaux nécessite un examen attentif de la surcharge spécifique au compilateur. La solution proposée offre une alternative portable en allouant et en détruisant les éléments du tableau individuellement.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn