Détection à l’exécution de la suppression de la mémoire

Le code:

int *ptr = new int[10]; int *q = ptr; delete q; 

fonctionne correctement sans aucun problème (pas d’erreur d’exécution).

Cependant, le code suivant:

 int *ptr = new int[10]; int *q = ptr; q++; delete q; 

entraîne une erreur d’exécution.

J’utilise Microsoft Visual Studio-8 et Win-7 comme plate-forme.

Je ne suis pas en mesure de comprendre pourquoi il y a une erreur d’exécution dans le second cas?

Votre code provoque un comportement indéfini . Un comportement indéfini signifie que tout peut arriver, le comportement ne peut pas être défini. Le programme fonctionne simplement par pure chance, son comportement ne peut être expliqué.

Fondamentalement,

Si vous allouez de la mémoire dynamic avec new vous devez utiliser delete pour le libérer.

Si vous allouez de la mémoire dynamic avec new[] vous devez utiliser delete[] pour le libérer.

C’est un comportement indéfini de passer une adresse à delete qui n’a pas été renvoyée par new .
Voici la citation de la norme.

Conformément à la norme C ++ 03 § 3.7.4.2-3:

Si une fonction de désaffectation se termine en lançant une exception, le comportement est indéfini. La valeur du premier argument fourni à une fonction de libération peut être une valeur de pointeur nulle; Si oui, et si la fonction de désallocation est une fonction fournie dans la bibliothèque standard, l’appel n’a aucun effet. Sinon, la valeur fournie à l’opérateur delete(void*) dans la bibliothèque standard doit être l’une des valeurs renvoyées par un appel précédent de l’opérateur new(std::size_t) ou de l’ operator new(std::size_t, const std::nothrow_-t&) dans la bibliothèque standard, et la valeur fournie à l’opérateur delete[](void*) dans la bibliothèque standard doit être l’une des valeurs renvoyées par un appel précédent de l’ operator new[](std::size_t) ou operator new[](std::size_t, const std::nothrow_t&) dans la bibliothèque standard.

En C ++, il est préférable d’utiliser RAII (SBRM) en utilisant des pointeurs Smart au lieu de pointeurs bruts, qui prennent automatiquement en charge les désallocations de mémoire.

Il y a deux erreurs ici:

  1. Vous ne pouvez pas delete un pointeur qui n’a pas été renvoyé par new .
  2. Vous ne pouvez pas delete un pointeur renvoyé par new[] – vous devez utiliser delete[] .

Ainsi, le premier extrait ne fonctionne que par coïncidence et il n’y a pas d’erreur uniquement parce que vous utilisez un type primitif. S’il s’agissait d’UDT, les destructeurs ne fonctionneraient pas.

En outre, vous devez utiliser des conteneurs et des pointeurs intelligents, au lieu de new et delete bruts.

Parce que vous devez transmettre le résultat non modifié de new à supprimer. C’est comme ça que les choses fonctionnent, c’est-à-dire le contrat API de new / delete.

Parce que vous avez modifié l’adresse q pointée, puis essayé de le supprimer.

Vous ne devriez jamais essayer de delete les new retours. Tout le rest est un comportement indéfini.