Een aanwijzer verwijderen in C++

Context: ik probeer mijn hoofd rond aanwijzingen te wikkelen, we hebben ze net een paar weken geleden op school gezien en tijdens het oefenen van vandaag kwam ik een dwaas tegen? probleem, het kan heel eenvoudig voor je zijn, maar ik heb weinig tot geen programmeerervaring.

Ik heb in SO nogal wat vragen gezien over het verwijderen van pointers, maar ze lijken allemaal te maken te hebben met het verwijderen van een klasse en niet met een ‘eenvoudige’ pointer (of wat de juiste term ook is), hier is de code I’ ik probeer te rennen:

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

Dus mijn vragen zijn:

  1. Waarom werkt het eerste geval niet? Lijkt het meest eenvoudige gebruik om een ​​aanwijzer te gebruiken en te verwijderen? De fout zegt dat het geheugen niet is toegewezen, maar ‘cout’ heeft een adres geretourneerd.
  2. In het tweede voorbeeld wordt de fout niet geactiveerd, maar het berekenen van de waarde van myPointer nog levert een geheugenadres op?
  3. Werkt #3 echt? Lijkt mij te werken, de aanwijzer slaat geen adres meer op, is dit de juiste manier om een ​​aanwijzer te verwijderen?

Sorry voor de lange vraag, wilde dit zo duidelijk mogelijk maken, ook om te herhalen, ik heb weinig programmeerervaring, dus als iemand dit zou kunnen beantwoorden in termen van leken, zou dat zeer op prijs worden gesteld!


Antwoord 1, autoriteit 100%

1 & 2

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

De eerste variabele is op de stapel toegewezen. U kunt alleen verwijderen oproepen op geheugen dat u dynamisch (op de heap) hebt toegewezen met behulp van de new-operator.

3.

  myPointer = NULL;
  delete myPointer;

Het bovenstaande deed helemaal niets. Je hebt niets vrijgemaakt, omdat de aanwijzer naar NULL wees.


Het volgende mag niet worden gedaan:

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

Je wees het op NULL, en liet gelekt geheugen achter (de nieuwe int die je had toegewezen).
Je zou het geheugen moeten vrijmaken waar je naar wees. Er is geen manier meer om toegang te krijgen tot die toegewezen new int, vandaar geheugenlek.


De juiste manier:

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

De betere manier:

Als je C++ gebruikt, gebruik dan geen onbewerkte pointers. Gebruik in plaats daarvan slimme aanwijzers die deze dingen voor u kunnen regelen met weinig overhead. C++11 wordt geleverd met verschillende.


Antwoord 2, autoriteit 15%

Ik denk dat je niet helemaal begrijpt hoe aanwijzers werken.
Als je een aanwijzer hebt die naar een bepaald geheugen wijst, zijn er drie verschillende dingen die je moet begrijpen:
– er is “wat wordt gewezen” door de aanwijzer (het geheugen)
– dit geheugenadres
– niet alle aanwijzers hoeven in hun geheugen te worden verwijderd: u hoeft alleen geheugen te verwijderen dat dynamisch is toegewezen (gebruikte new-operator).

Stel je voor:

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!

Toen je dat deed

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++ staat toe dat je probeert een pointer te delete die naar null verwijst, maar het doet eigenlijk niets, geeft alleen geen foutmelding.


Antwoord 3, autoriteit 7%

Aanwijzers lijken op normale variabelen in die zin dat u ze niet hoeft te verwijderen. Ze worden uit het geheugen verwijderd aan het einde van de uitvoering van een functie en/of het einde van het programma.

U kunt echter pointers gebruiken om een ​​’blok’ geheugen toe te wijzen, bijvoorbeeld als volgt:

int *some_integers = new int[20000]

Hiermee wordt geheugenruimte toegewezen voor 20000 gehele getallen. Handig, omdat de Stack een beperkte grootte heeft en je misschien wilt rommelen met een grote lading ‘ints’ zonder een stack overflow-fout.

Telkens wanneer u nieuw aanroept, moet u aan het einde van uw programma ‘verwijderen’, omdat u anders een geheugenlek krijgt en een deel van het toegewezen geheugen nooit wordt teruggegeven aan andere programma’s. Om dit te doen:

delete [] some_integers;

Hopelijk helpt dat.


Antwoord 4, autoriteit 4%

Er is een regel in C++, voor elke nieuwe is er een delete.

  1. Waarom werkt het eerste geval niet? Lijkt het meest eenvoudige gebruik om een ​​aanwijzer te gebruiken en te verwijderen? De fout zegt dat het geheugen niet is toegewezen, maar ‘cout’ heeft een adres geretourneerd.

nieuw wordt nooit genoemd. Het adres dat cout afdrukt is dus het adres van de geheugenlocatie van myVar, of in dit geval de waarde die aan myPointer is toegewezen. Door te schrijven:

myPointer = &myVar;

je zegt:

myPointer = Het adres waar de gegevens in myVar zijn opgeslagen

  1. In het tweede voorbeeld wordt de fout niet geactiveerd, maar een berekening van de waarde van myPointer levert nog steeds een geheugenadres op?

Het retourneert een adres dat verwijst naar een geheugenlocatie die is verwijderd. Omdat u eerst de aanwijzer maakt en de waarde ervan toewijst aan myPointer, ten tweede verwijdert u deze en ten derde drukt u hem af. Dus tenzij u een andere waarde toewijst aan myPointer, blijft het verwijderde adres behouden.

  1. Werkt #3 echt? Lijkt mij te werken, de aanwijzer slaat geen adres meer op, is dit de juiste manier om een ​​aanwijzer te verwijderen?

NULL is gelijk aan 0, je verwijdert 0, dus je verwijdert niets. En het is logisch dat er 0 wordt afgedrukt omdat u dat deed:

myPointer = NULL;

wat gelijk is aan:

myPointer = 0;

Antwoord 5, autoriteit 2%

  1. U probeert een variabele te verwijderen die op de stapel is toegewezen. Je kunt dit niet doen
  2. Het verwijderen van een aanwijzer vernietigt eigenlijk geen aanwijzer, alleen het bezette geheugen wordt teruggegeven aan het besturingssysteem. Je hebt er toegang toe totdat het geheugen wordt gebruikt voor een andere variabele, of op een andere manier wordt gemanipuleerd. Het is dus een goede gewoonte om een ​​aanwijzer op NULL (0) te zetten na het verwijderen.
  3. Het verwijderen van een NULL-aanwijzer verwijdert niets.

Antwoord 6

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.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes