views:

94

answers:

2

On Learn C++, they wrote this to free memory:

int *pnValue = new int; // dynamically allocate an integer
*pnValue = 7; // assign 7 to this integer
delete pnValue;
pnValue = 0;

My question is: "Is the last statement needed to free the memory correctly, completly?"

I thought that the pointer *pnValue was still on the stack and new doesn't make any sense to the pointer. And if it is on the stack it will be cleaned up when the application leaves the scope (where the pointer is declared in), isn't it?

+3  A: 

It's not necessary, but it's always a good idea to set pointers to NULL (0) when you're done with them. That way if you pass it to a function (which would be a bug), it will likely give you an error rather than trying to operate on invalid memory (makes the bug much easier to track down). And it also makes conditionals simpler.

Cogwheel - Matthew Orlando
@Cogwheel ~ Yes, but isn't that in reverse order? Would you really set it after delete?
drachenstern
A better still idea is to ensure that the pointer goes out of scope when it is freed. Don't have free pointers scattered throughout your code. Wrap them in RAII classes or smart pointers.
jalf
@drache: Do you mean `p = 0; delete p;`? That does not make any sense and results in a memory leak.
FredOverflow
@drachenstern, you can't set it before the delete, otherwise you won't be able to delete it anymore.
Cogwheel - Matthew Orlando
@jalf: well sure, but that's changing the context of the question ;)
Cogwheel - Matthew Orlando
+2  A: 

Setting a pointer to NULL (or zero) after deleting it is not necessary. However it is good practice. For one thing, you won't be able to access some random data if you later dereference the pointer. Additionally, you'll often find code with the following:

if(ptr)
{
  delete ptr;
  ptr = NULL;
}

So setting the pointer to NULL will ensure it won't be deleted twice.

Finally, you might find code like this:

void foo(bar *ptr)
{
  if(!ptr) throw Exception(); // or return, or do some other error checking
  // ...
}

And you'd probably want that safety check to be hit.

Niki Yoshiuchi
The `if` is totally redundant here -.- Just do `delete ptr; ptr = 0;`. Deleting a null pointer is a no-op, thus when you assign the zero, not even an `if` check is needed anymore.
Johannes Schaub - litb
Whoops misread it.
Niki Yoshiuchi
I think it's arguable that it's good to set it to null after deleting it. If you've deleted a pointer, it's value should be irrelevant because the *last* thing you do with a pointer is delete it. If you still have it around, you're doing it wrong. Not only that, you shouldn't really need to delete it anyway, it should be done for you (which goes back to not having to worry about using it again.) If I do end up having poor design and keep pointers around that I don't need, at least a non-null value might crash and let me know there's a problem with my design, ...
GMan
GMan
I'm a believer in RAII so I completely agree. However, you don't always have that luxury (libraries, other people's code, etc). I might be wrong about this, but I'm pretty sure that dereferencing a NULL pointer is more likely to cause a crash than dereferencing an invalid pointer. Finally my foo example was completely contrived but I've come across code like that fairly often, for better or worse).
Niki Yoshiuchi
@GMan "If you've deleted a pointer, it's value should be irrelevant because the last thing you do with a pointer is delete it." only applies to local nonstatic pointers though. Everything else will remain visible and alive so that you can gain from it being `0` to crash early or (more important, i think) to have *additional* possibilities to analyze the state of the pointer for tracing, lazy-loading of resources, etc.
Johannes Schaub - litb
@Johannes: But that's leaving the "it's good practice for safety" land and moving to "I'm using it's value as a flag" land. :]
GMan
@Johannes: Wouldn't `delete p; p = reinterpret_cast<int*>(0xd31373d);` (that number being 1337-speak for "deleted") be even better in terms of crashing deterministically? :)
FredOverflow
@GMan that was only the second part my answer. The primary part was that the pointer is still visible and so it does make a difference whether or not you set it to 0: "If you still have it around, you're doing it wrong" - so you say that if you have a pointer as member of a class, you do it wrong. "at least a non-null value might crash and let me know there's a problem with my design" - it's exactly the opposite. A null-value will certainly yield to a crash on most platforms when dereferenced, while a nonnull value will possibly go silently the wrong way for most usecases.
Johannes Schaub - litb
There are two important use-cases here: *deleting* (this most probably happens only once, and corresponds to the allocation), and *using* the pointer. The latter will certainly crash with null pointers on many platforms and use-cases (accessing a value), while it will probably not crash with non-null pointers. The former use-case happens much more seldom and has a well-defined meaning for null pointers, and only gives you feedback about a problem when your libraries are specially instructed to do so (`MALLOC_CHECK_`), and even then only *sometimes* with undefined results.
Johannes Schaub - litb
... Thus i see null pointers as superior when the pointer is long-lived as a member or namespace scope object.
Johannes Schaub - litb