Maison >développement back-end >C++ >Le placement est-il nouveau pour les tableaux vraiment portables en 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!