web-dev-qa-db-fra.com

Suppression d'un tableau de caractères

Cette question est liée à celle-ci . Compte tenu de ce code:

char *p = new char[200];
delete[] p;

que se passerait-il si vous définissez p[100] = '\0' avant de supprimer p?

J'ai eu du code où j'ai eu une erreur de débogage lorsque j'ai essayé de supprimer un tableau de caractères non terminé par un caractère nul, quelque chose sur la suppression de la mémoire de tas qui n'est pas affectée. Il semblait supprimer la mémoire hors des limites du tableau.

23
DaClown

Le code:

char *p = new char[200];
p[100] = '\0';
delete[] p;

est parfaitement valide C++. delete ne connaît pas ou ne se soucie pas des chaînes terminées par null, donc votre erreur doit avoir eu une autre cause.

41
anon

Rien de spécial ne se passerait. Vous écririez à un endroit au milieu de la mémoire allouée (100 octets à part le début, 99 octets avant la fin de la mémoire allouée).

Ensuite, vous libéreriez cette mémoire allouée. Le compilateur le traitera exactement comme nous l'attendions. La mémoire allouée par cela est complètement indépendante des chaînes terminées par null. Vous pouvez coller tout ce que vous voulez dans cette mémoire. C'est un morceau de stockage "brut", vous pouvez même créer un objet C++ arbitraire dans cette mémoire (placement nouveau).

Votre bug est ailleurs. Par exemple, une erreur courante est celle-ci, où le constructeur est appelé une fois, mais le destructeur est appelé deux fois, en supprimant deux fois quelque chose:

struct A { P *p; A() { p = new P; } ~A() { delete p; } };
A getA() { return A(); } int main() { A a = getA(); }

Maintenant, ce qui se passe, c'est que le constructeur par défaut est appelé une fois et que l'objet créé est copié zéro ou plusieurs fois. Mais le destructeur est exécuté pour chaque copie créée. Ainsi, vous appellerez le destructeur sur le pointeur plus d'une fois, ce qui conduira à de tels bugs étranges. La bonne façon de corriger que est d'utiliser un pointeur intelligent, comme shared_ptr. En tant qu'exercice, vous pouvez également le faire sans, en écrivant des constructeurs de copie appropriés qui copient l'objet et allouent de la mémoire dans le constructeur de copie, de sorte que la copie et l'objet d'origine respectif gardent des pointeurs distincts.

8

Je pense que vous confondez un ancien tableau de caractères avec un tableau de caractères représentant une chaîne de style C. L'opérateur de suppression C++ ne se soucie pas d'un tableau de chaînes de style C. Tout ce qu'il verra, c'est un tableau de caractères. Ce n'est vraiment pas différent que de supprimer un tableau d'int.

La présence ou l'absence du terminateur nul n'est pertinente que dans les fonctions qui traitent un char* comme une chaîne de style C.

6
JaredPar

Ça ne devrait pas avoir d'importance. delete [] doit être utilisé pour supprimer un tableau alloué dynamiquement quel que soit son contenu.

3
aJ.

Pour autant que je sache, cela devrait très bien fonctionner. Vous allouez un morceau de mémoire, et le système d'exploitation devrait en garder la trace et pouvoir le désallouer lorsque cela vous sera demandé. Peu importe les valeurs que vous mettez dans le tampon que vous avez alloué.

Coller un NULL au milieu d'un tableau de caractères interférerait certainement avec les fonctions de chaîne C telles que strcmp, strlen, etc., mais c'est une tout autre affaire.

1
Dima

Comme d'autres l'ont noté, le code que vous avez publié est parfaitement valide et ne devrait pas poser de problème.

L'erreur peut être due à la modification de la valeur de p quelque part entre les deux.

0
Joey