web-dev-qa-db-fra.com

Supprimer un pointeur en C ++

Contexte: J'essaie de comprendre les indicateurs, nous les avons vus il y a quelques semaines à l'école et en pratiquant aujourd'hui, je suis tombé sur une idiote? problème, il peut être très simple pour vous, mais j’ai peu d’expérience en programmation.

J'ai vu pas mal de questions dans SO à propos de la suppression de pointeurs, mais elles semblent toutes liées à la suppression d'une classe et non à un pointeur 'simple' (ou quel que soit le terme approprié), voici la code que j'essaye de lancer:

#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.

}

Donc mes questions sont:

  1. Pourquoi le premier cas ne fonctionne-t-il pas? Semble l’utilisation la plus simple d’utiliser et de supprimer un pointeur? L'erreur indique que la mémoire n'a pas été allouée mais que 'cout' a renvoyé une adresse.
  2. Dans le second exemple, l'erreur n'est pas déclenchée, mais un coût de la valeur de myPointer toujours renvoie une adresse mémoire?
  3. Le n ° 3 fonctionne-t-il vraiment? Cela semble fonctionner pour moi, le pointeur ne stocke plus d'adresse, est-ce la bonne façon de supprimer un pointeur?

Désolé pour la longue question, je voulais que ce soit aussi clair que possible, et je le répète aussi, je n’ai que peu d’expérience en programmation. Si quelqu'un pouvait y répondre en termes simples, ce serait grandement apprécié!

76
leopic

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 ne pouvez appeler la suppression que sur la mémoire que vous avez allouée dynamiquement (sur le tas) à l'aide de l'opérateur new.

3.

  myPointer = NULL;
  delete myPointer;

Ce qui précède n'a rien du tout . Vous n'avez rien libéré, le pointeur pointant vers NULL.


Les opérations suivantes ne doivent pas être effectuées:

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

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


La manière correcte:

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

La meilleure façon de faire:

Si vous utilisez C++, n'utilisez pas des pointeurs bruts. Utilisez pointeurs intelligents à la place, qui peut gérer ces choses pour vous avec un minimum de temps système. C++ 11 est livré avec plusieurs .

147

Je crois que vous ne comprenez pas vraiment comment fonctionnent les pointeurs.
Lorsque vous avez un pointeur pointant vers une mémoire, vous devez comprendre trois choses différentes:
- il y a "ce qui est pointé" par le pointeur (la mémoire)
- cette adresse mémoire
- la mémoire de tous les pointeurs ne doit pas nécessairement être supprimée: vous devez uniquement supprimer la mémoire allouée dynamiquement (opérateur new utilisé).

Imaginer:

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 vous avez 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.

C++ vous permet d'essayer de delete un pointeur qui pointe sur null, mais il ne fait rien, il ne génère aucune erreur.

18
salgadokk

Les pointeurs sont similaires aux variables normales en ce sens qu'il n'est pas nécessaire 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 cependant utiliser des pointeurs pour allouer un "bloc" de mémoire, par exemple comme ceci:

int *some_integers = new int[20000]

Cela allouera de la mémoire pour 20000 entiers. Utile, parce que la pile a une taille limitée et que vous voudrez peut-être vous gâcher avec une grosse charge d’intrants sans erreur de débordement de pile.

Chaque fois que vous appelez un nouveau, vous devez alors "supprimer" à la fin de votre programme, sinon vous obtiendrez une fuite de mémoire et une partie de l'espace mémoire alloué ne sera jamais restituée pour que les autres programmes l'utilisent. Pour faire ça:

delete [] some_integers;

J'espère que ça t'as aidé.

11
user3728501

Il y a une règle en C++, pour chaque nouvea il y a un supprimer.

  1. Pourquoi le premier cas ne fonctionne-t-il pas? Semble l'utilisation la plus simple à utiliser pour supprimer un pointeur? L'erreur indique que la mémoire n'a pas été allouée mais que 'cout' a renvoyé une adresse.

new n'est jamais appelé. Ainsi, l'adresse imprimée par cout est l'adresse de l'emplacement mémoire de myVar, ou la valeur attribuée à myPointer dans ce cas. En écrivant:

myPointer = &myVar;

vous dites:

myPointer = Adresse de stockage des données dans myVar

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

Il renvoie une adresse qui pointe vers un emplacement de mémoire qui a été supprimé. Parce que vous créez d'abord le pointeur et lui attribuez sa valeur, ensuite vous le supprimez, vous l'imprimez en troisième lieu. Donc, sauf si vous attribuez une autre valeur à myPointer, l'adresse supprimée restera.

  1. Le n ° 3 fonctionne-t-il vraiment? Cela semble fonctionner pour moi, le pointeur n'enregistre plus d'adresse, est-ce la bonne façon de supprimer un pointeur?

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

myPointer = NULL;

qui est égal à:

myPointer = 0;
7
fonZ
  1. Vous essayez de supprimer une variable allouée sur la pile. Tu ne peux pas faire ça
  2. La suppression d'un pointeur ne détruit pas réellement un pointeur, seule la mémoire occupée est restituée au système d'exploitation. Vous pouvez y accéder jusqu'à ce que la mémoire soit utilisée pour une autre variable ou autrement manipulée. Il est donc recommandé de définir un pointeur sur NULL (0) après la suppression.
  3. La suppression d'un pointeur NULL ne supprime rien.
4
Hakan Serce
int value, *ptr;

value = 8;
ptr = &value;
// ptr points to value, which lives on a stack frame.
// you are not responsible for managing its lifetime.

ptr = new int;
delete ptr;
// yes this is the normal way to manage the lifetime of
// dynamically allocated memory, you new'ed it, you delete it.

ptr = nullptr;
delete ptr;
// this is illogical, essentially you are saying delete nothing.
1
Casper Beyer