97

Context: I'm trying to wrap my head around pointers, we just saw them a couple of weeks ago in school and while practicing today I ran into a silly? issue, it can be super straightforward to you but I have little to none programming experience.

I've seen quite a few questions over in SO about deleting pointers but they all seem to be related to deleting a class and not a 'simple' pointer (or whatever the proper term might be), here's the code I'm trying to run:

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

}

So my questions are:

  1. Why won't the first case work? Seems the most straightforward use to use and delete a pointer? The error says the memory wasn't allocated but 'cout' returned an address.
  2. On the second example the error is not being triggered but doing a cout of the value of myPointer still returns a memory address?
  3. Does #3 really work? Seems to work to me, the pointer is no longer storing an address, is this the proper way to delete a pointer?

Sorry for the long question, wanted to make this as clear as possible, also to reiterate, I have little programming experience, so if someone could answer this using layman's terms, it would be greatly appreciated!

Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120
leopic
  • 2,718
  • 1
  • 24
  • 42
  • 16
    The reason you don't see the first example is because it's wrong. Only `delete` what you `new`. It's also not required for the pointer to set itself to NULL after you delete it. If you want safety there, use smart pointers, which free the memory for you and give errors when you try to access them when they don't hold something. – chris Nov 04 '12 at 22:03
  • Hmm okay, I'm not sure what smart pointers are, but I'll look into it, thanks! – leopic Nov 05 '12 at 05:25
  • 1
    In a nutshell, they do what I described. In order to hold something new, you call `reset` and it frees the old one. To free it without replacement, you call `release`. When it goes out of scope, it's destroyed, and could free the memory based on what type it is. `std::unique_ptr` is meant for only one owner. `std::shared_ptr` frees it when the last owner stops owning the resource. They are also exception safe. If you allocate a resource with one, and then encounter an exception, the resource will be properly freed. – chris Nov 05 '12 at 14:40

6 Answers6

175

1 & 2

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

The first variable was allocated on the stack. You can call delete only on memory you allocated dynamically (on the heap) using the new operator.

3.

  myPointer = NULL;
  delete myPointer;

The above did nothing at all. You didn't free anything, as the pointer pointed at NULL.


The following shouldn't be done:

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

You pointed it at NULL, leaving behind leaked memory (the new int you allocated). You should free the memory you were pointing at. There is no way to access that allocated new int anymore, hence memory leak.


The correct way:

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

The better way:

If you're using C++, do not use raw pointers. Use smart pointers instead which can handle these things for you with little overhead. C++11 comes with several.

Community
  • 1
  • 1
Anirudh Ramanathan
  • 43,868
  • 20
  • 121
  • 177
  • 13
    "On the stack" is an implementation detail -- one that C++ conspicuously avoids mentioning. The more correct term is "with automatic storage duration". (C++11, 3.7.3) – cHao Nov 05 '12 at 00:06
  • 4
    Thank you, I selected your answer for a) explaining what was wrong and b) giving a best practice, thanks much! – leopic Nov 05 '12 at 05:32
  • I would like to add, no matter how old this post is (for the sake of googlers), `delete myPointer` deallocates `*myPointer`, and `myPointer` is no longer pointing at anything. It will be destroyed at the end of the scope. – Tqn Jul 08 '14 at 08:02
  • 6
    @Tqn That isn't right. `delete myPointer` deallocates `*myPointer`. That is correct. But `myPointer` continues to point at a memory location that has been freed and shouldn't be used as it is UB. It will be inaccessible after the end of the scope only IF it was a local variable in the first place. – Anirudh Ramanathan Jul 08 '14 at 11:44
  • 2
    @DarkCthulhu Thanks! (I literally) learn something `new` every day. (I'm cheesy!) – Tqn Jul 09 '14 at 09:14
  • if i am not mistaken pointer is still on stack after we assign pointer to null? how do you remove pointer from stack manually, without waiting program to end? – sensei Oct 06 '14 at 08:08
  • 1
    @AmelSalibasic The memory associated with the variable on the stack will be freed only once it goes out of scope. Assigning it to `NULL` prevents us from misusing it later on. – Anirudh Ramanathan Oct 06 '14 at 16:21
  • @Anirudh Ramanathan Thank you so much for your answer. I searched for this answer for a while now. It always baffled me because I was pointing pointer to NULL before delete. – j. cho Sep 14 '20 at 11:51
24

I believe you're not fully understanding how pointers work.
When you have a pointer pointing to some memory there are three different things you must understand:
- there is "what is pointed" by the pointer (the memory)
- this memory address
- not all pointers need to have their memory deleted: you only need to delete memory that was dynamically allocated (used new operator).

Imagine:

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!

When you did

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++ allows that you try to delete a pointer that points to null but it doesn't actually do anything, just doesn't give any error.

salgadokk
  • 241
  • 1
  • 3
  • 2
    Thanks, THIS was super helpful, I thought I HAD to delete all pointers, didn't know that was only for the ones that were new'd, thanks. – leopic Nov 05 '12 at 05:31
13

Pointers are similar to normal variables in that you don't need to delete them. They are removed from memory at the end of a functions execution and/or the end of the program.

You can however use pointers to allocate a 'block' of memory, for example like this:

int *some_integers = new int[20000]

This will allocate memory space for 20000 integers. Useful, because the Stack has a limited size and you might want to mess about with a big load of 'ints' without a stack overflow error.

Whenever you call new, you should then 'delete' at the end of your program, because otherwise you will get a memory leak, and some allocated memory space will never be returned for other programs to use. To do this:

delete [] some_integers;

Hope that helps.

FreelanceConsultant
  • 9,832
  • 22
  • 88
  • 173
  • 1
    I want to just add that the allocated memory WILL be returned for other programs to use, but only AFTER your program has finished executing. – sk4l Jan 17 '16 at 02:14
7

There is a rule in C++, for every new there is a delete.

  1. Why won't the first case work? Seems the most straightforward use to use and delete a pointer? The error says the memory wasn't allocated but 'cout' returned an address.

new is never called. So the address that cout prints is the address of the memory location of myVar, or the value assigned to myPointer in this case. By writing:

myPointer = &myVar;

you say:

myPointer = The address of where the data in myVar is stored

  1. On the second example the error is not being triggered but doing a cout of the value of myPointer still returns a memory address?

It returns an address that points to a memory location that has been deleted. Because first you create the pointer and assign its value to myPointer, second you delete it, third you print it. So unless you assign another value to myPointer, the deleted address will remain.

  1. Does #3 really work? Seems to work to me, the pointer is no longer storing an address, is this the proper way to delete a pointer?

NULL equals 0, you delete 0, so you delete nothing. And it's logic that it prints 0 because you did:

myPointer = NULL;

which equals:

myPointer = 0;
fonZ
  • 2,342
  • 3
  • 18
  • 37
4
  1. You are trying to delete a variable allocated on the stack. You can not do this
  2. Deleting a pointer does not destruct a pointer actually, just the memory occupied is given back to the OS. You can access it untill the memory is used for another variable, or otherwise manipulated. So it is good practice to set a pointer to NULL (0) after deleting.
  3. Deleting a NULL pointer does not delete anything.
Hakan Serce
  • 10,888
  • 3
  • 26
  • 43
2
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.
Casper Beyer
  • 1,946
  • 1
  • 19
  • 34
  • 1
    In addition, check out this lecture on stack frames http://www.youtube.com/watch?v=bjObm0hxIYY, and http://www.youtube.com/watch?v=Rxvv9krECNw on pointers. – Casper Beyer Nov 05 '12 at 05:53