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:
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é!
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 .
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.
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é.
Il y a une règle en C++, pour chaque nouvea il y a un supprimer.
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
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.
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;
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.