supprimer [] fourni un pointeur nouvelle édition modifiée. Comportement non défini?
-
16-09-2019 - |
Question
J'ai vu un code comme ci-dessous lors d'une session d'examen par les pairs code:
char *s = new char[3];
*s++ = 'a';
*s++ = 'b';
*s++='\0';
delete []s; // this may or may not crash on some or any day !!
Tout d'abord, je sais que dans la norme C ++, pointant vers un passé la taille du tableau est Ö.K mais l'accès il en résulte un comportement non défini. Je crois donc que la dernière ligne *s++='\0'
est très bien. Mais si je me souviens bien, les mandats standards C ++ qui delete
doivent être fournis le même pointeur que new
retourné.
Je crois signifie que le pointeur renvoyé ne doit pas être trafiqué avec. Je suppose que c'est parce que new
pourrait garder quelques informations d'ordre administratif avant l'adresse de retour que delete
pourrait utiliser. Le déplacement du pointeur new
'd pourrait rendre cette inaccessible.
est-il un comportement non défini ou la mise en œuvre défini ou non spécifié? Quelqu'un peut-il confirmer cela s'il vous plaît? De préférence, en pointant à l'endroit correct dans la norme C ++.
Dans la version préliminaire disponible gratuitement du projet C ++ standard (Draft_SC22-N-4411.pdf) a les détails dans la section 5.3.5. Je l'ai obtenu de la page d'accueil de Bjarne.
La solution
de la norme C ++, section 5.3.5 / 2:
la valeur de l'opérande de suppression est la valeur du pointeur qui a donné lieu à partir d'un tableau précédent nouvelle expression. Dans le cas contraire, le comportement est indéfini
Autres conseils
Oui, vous devez supprimer [] le pointeur d'origine vous a été donné par le nouveau; dans ce cas, ce serait un pointeur sur la tête de la matrice, au lieu de la queue. Le code ici supprime un autre objet aléatoire non précisé.
Oui, rappeler comment cela est souvent mis en œuvre: de nouveaux appels vraiment malloc, ce qui rend un pointeur vers (void*)(&(((int*)p)[1]))
, où p est le début réel de la mémoire allouée, et le premier int est la taille de la mémoire réelle, nous sommes revenus .
Le pointeur que nous obtenons est un sizeof (int) (ou quel que soit l'alignement exige) plus loin dans la mémoire réelle allouée. Nous déposons là-bas notre objet, laissant la taille réelle sans être dérangé.
Ensuite, lorsque ce pointeur est passé à supprimer, qui passe à libérer, semble libre un int avant le pointeur passé, pour trouver la taille qui est en cours de rendu.
repassant autre chose que ce que nous avons va dire que le libre pense une quantité arbitraire de mémoire réelle est passée en arrière, et il va bousiller la liste libre en conséquence.
Encore une fois, cela est la façon dont il est souvent mis en œuvre, comment nouvelle, supprimer, malloc ou libre sont tenus d'être mis en œuvre.