118 votes

Suppression d'un pointeur en C++

Le contexte : J'essaie de me faire une idée des pointeurs, nous les avons vus il y a quelques semaines à l'école et en m'exerçant aujourd'hui, j'ai rencontré un problème stupide, qui peut être très simple pour vous, mais j'ai peu ou pas d'expérience en programmation.

J'ai vu pas mal de questions sur SO à propos de la suppression des pointeurs mais elles semblent toutes concerner la suppression d'une classe et non d'un 'simple' pointeur (ou quel que soit le terme approprié), voici le code que j'essaie d'exécuter :

#include <iostream>;

using namespace std;

int main() {
  int myVar,
      *myPointer;

  myVar = 8;
  myPointer = &myVar;

  cout << "delete-ing pointers " << endl;
  cout << "Memory address: " << myPointer << endl;

  // Seems I can't *just* delete it, as it triggers an error 
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // Error: a.out(14399) malloc: *** error for object 0x7fff61e537f4:
  // pointer being freed was not allocated
  // *** set a breakpoint in malloc_error_break to debug
  // Abort trap: 6

  // Using the new keyword befor deleting it works, but
  // does it really frees up the space? 
  myPointer = new int;
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // myPointer continues to store a memory address.

  // Using NULL before deleting it, seems to work. 
  myPointer = NULL;
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // myPointer returns 0.

}

Mes questions sont donc les suivantes :

  1. Pourquoi le premier cas ne fonctionne pas ? Il semble que l'utilisation et la suppression d'un pointeur soit la plus simple ? L'erreur dit que la mémoire n'a pas été allouée mais que 'cout' a renvoyé une adresse.
  2. Dans le deuxième exemple, l'erreur n'est pas déclenchée, mais un cout de la valeur de myPointer est effectué. toujours renvoie une adresse mémoire ?
  3. Le numéro 3 fonctionne-t-il vraiment ? Il me semble que cela fonctionne, le pointeur ne stocke plus d'adresse, est-ce la bonne façon de supprimer un pointeur ?

Désolé pour cette longue question, je voulais que ce soit aussi clair que possible. Je répète également que j'ai peu d'expérience en programmation, donc si quelqu'un pouvait répondre à cette question en termes simples, ce serait très apprécié !

207voto

Anirudh Ramanathan Points 25113

1 & 2

myVar = 8; //not dynamically allocated. Can't call delete on it.
myPointer = new int; //dynamically allocated, can call delete on it.

La première variable a été allouée sur la pile. Vous pouvez appeler delete uniquement sur la mémoire que vous avez allouée dynamiquement (sur le tas) en utilisant la fonction new opérateur.

3.

  myPointer = NULL;
  delete myPointer;

Ce qui précède a fait rien du tout . Vous n'avez rien libéré, car le pointeur pointait sur NULL.


Ce qui suit ne devrait pas être fait :

myPointer = new int;
myPointer = NULL; //leaked memory, no pointer to above int
delete myPointer; //no point at all

Vous l'avez pointé vers NULL, laissant derrière vous de la mémoire perdue (le nouvel int que vous avez alloué). Vous devriez libérer la mémoire que vous pointiez. Il n'y a aucun moyen d'accéder à la mémoire allouée new int plus, d'où la fuite de mémoire.


Le bon chemin :

myPointer = new int;
delete myPointer; //freed memory
myPointer = NULL; //pointed dangling ptr to NULL

La meilleure façon :

Si vous utilisez C++, ne pas utiliser des pointeurs bruts. Utiliser pointeurs intelligents à la place qui peut gérer ces choses pour vous avec peu de frais généraux. C++11 est livré avec plusieurs .

31voto

salgadokk Points 271

Je crois que vous ne comprenez pas bien le fonctionnement des pointeurs.
Lorsque vous avez un pointeur qui pointe vers une mémoire, il y a trois choses différentes que vous devez comprendre :
- il y a "ce qui est pointé" par le pointeur (la mémoire)
- cette adresse mémoire
- il n'est pas nécessaire de supprimer la mémoire de tous les pointeurs : vous ne devez supprimer que la mémoire qui a été allouée dynamiquement (utilisée new opérateur).

Imaginez :

int *ptr = new int; 
// ptr has the address of the memory.
// at this point, the actual memory doesn't have anything.
*ptr = 8;
// you're assigning the integer 8 into that memory.
delete ptr;
// you are only deleting the memory.
// at this point the pointer still has the same memory address (as you could
//   notice from your 2nd test) but what inside that memory is gone!

Quand tu as fait

ptr = NULL;
// you didn't delete the memory
// you're only saying that this pointer is now pointing to "nowhere".
// the memory that was pointed by this pointer is now lost.

Le C++ permet d'essayer de delete un pointeur qui pointe vers null mais il ne fait rien, il ne donne pas d'erreur.

15voto

user3728501 Points 1345

Les pointeurs sont similaires aux variables normales en ce sens que vous n'avez pas besoin de les supprimer. Ils sont supprimés de la mémoire à la fin de l'exécution d'une fonction et/ou à la fin du programme.

Vous pouvez toutefois utiliser des pointeurs pour allouer un "bloc" de mémoire, par exemple comme ceci :

int *some_integers = new int[20000]

Cela allouera un espace mémoire pour 20000 entiers. C'est utile, car la pile a une taille limitée et vous pourriez vouloir vous amuser avec une grande quantité de 'ints' sans qu'une erreur de débordement de la pile ne se produise.

Chaque fois que vous appelez new, vous devez ensuite "supprimer" à la fin de votre programme, car sinon vous obtiendrez une fuite de mémoire, et une partie de l'espace mémoire alloué ne sera jamais restitué pour que d'autres programmes puissent l'utiliser. Pour ce faire, procédez comme suit

delete [] some_integers;

J'espère que cela vous aidera.

8voto

fonZ Points 1522

Il y a une règle dans le C++, pour chaque nouveau il existe un supprimer .

  1. Pourquoi le premier cas ne fonctionne pas ? Il semble que l'utilisation et la suppression d'un pointeur soit la plus simple ? L'erreur dit que la mémoire n'a pas été allouée mais que 'cout' a renvoyé une adresse.

new n'est jamais appelé. Donc l'adresse que cout imprime est l'adresse de l'emplacement mémoire de myVar, ou la valeur assignée à myPointer dans ce cas. En écrivant :

myPointer = &myVar;

vous dites :

myPointer = L'adresse où les données de myVar sont stockées.

  1. Dans le deuxième exemple, l'erreur n'est pas déclenchée, mais le fait de faire un cout de la valeur de myPointer renvoie toujours une adresse mémoire ?

Elle renvoie une adresse qui pointe vers un emplacement mémoire qui a été supprimé. En effet, vous créez d'abord le pointeur et attribuez sa valeur à myPointer, puis vous le supprimez et enfin vous l'imprimez. Donc, à moins que vous n'attribuiez une autre valeur à monPointeur, l'adresse supprimée restera.

  1. Le numéro 3 fonctionne-t-il vraiment ? Il me semble que cela fonctionne, le pointeur ne stocke plus d'adresse, est-ce la bonne façon de supprimer un pointeur ?

NULL est égal à 0, vous supprimez 0, donc vous ne supprimez rien. Et c'est logique qu'il imprime 0 parce que vous l'avez fait :

myPointer = NULL;

qui est égal à :

myPointer = 0;

4voto

Hakan Serce Points 6705
  1. Vous essayez de supprimer une variable allouée sur la pile. Vous ne pouvez pas le faire
  2. La suppression d'un pointeur ne le détruit pas en fait, mais la mémoire occupée est rendue à l'OS. Vous pouvez y accéder jusqu'à ce que la mémoire soit utilisée pour une autre variable, ou autrement manipulée. C'est donc une bonne pratique de mettre un pointeur à NULL (0) après l'avoir supprimé.
  3. La suppression d'un pointeur NULL ne supprime rien.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X