0

I was just wondering if there is any benefit in initializing a pointer to NULL, or in setting it to NULL after pointer deletion.

I've read on a few forums that setting to NULL after deletion is unnecessary, and that some compilers do not even consider the line. If it changes nothing, why do some people use it?

melbah
  • 61
  • 6
  • 4
    It may help debugging. –  Dec 20 '13 at 20:29
  • 4
    Ideally you shouldn't use owning pointer, use smart pointers instead. – 111111 Dec 20 '13 at 20:30
  • These days I have switched to nullptr – drescherjm Dec 20 '13 at 20:30
  • When you look at a deleted pointer in the debugger, you can't tell it's not pointing at a valid object. Setting it to NULL makes it easier to tell. Compiler may or may not optimize your assignment out when you enable optimization. –  Dec 20 '13 at 20:31
  • 1
    possible duplicate of [Is it good practice to NULL a pointer after deleting it?](http://stackoverflow.com/questions/1931126/is-it-good-practice-to-null-a-pointer-after-deleting-it) – Mooing Duck Dec 20 '13 at 21:22

7 Answers7

7

After

delete ptr;

the pointer object ptr probably still holds the same value it had before. It now points to a nonexistent object, so attempting to dereference it, or even to refer to its value, has undefined behavior. If you accidentally do something like:

delete ptr;
// ...
*ptr = 42;

it's likely to quietly clobber memory that you no longer own, or that may have been reallocated to some other object.

Setting the pointer to null:

delete ptr;
ptr = NULL; // or 0 or nullptr

means that an accidental attempt to dereference the pointer is more likely to cause your program to crash. (Crashing is a good thing in this context.)

Stealing Casey's comment:

C++11 §3.7.4.2 Deallocation Functions [basic.stc.dynamic.deallocation] para 4:

If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value (4.10), the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage. The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined.

If the pointer object is at the very end of its lifetime, you needn't bother, since there's no possibility of accidentally using it:

{
    int *ptr = new int(42);
    // ...
    delete ptr;
}

And as others have said, you're probably better off using some higher-level construct like smart pointers anyway.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 4
    +1 for 'Crashing is a good thing in this context.' –  Dec 20 '13 at 20:41
  • 1
    +1 "It now points to a nonexistent object" The follow-up after this is much more informative (particularly the invalidity of even *evaluating* the pointer value), as its value is *indeterminate* (i.e. we've no idea *what* it is). But try as I might I can find no reference in the standard that says so post-`delete`. It would be awesome if you could find that reference if it exists, but regardless, this answer works well without it. – WhozCraig Dec 20 '13 at 20:45
  • 2
    @WhozCraig C++11 §3.7.4.2 Deallocation Functions [basic.stc.dynamic.deallocation] para 4: "If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value (4.10), the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage. The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined." – Casey Dec 20 '13 at 20:54
  • @Casey thanks. I was stuck in the operators specs for some reason. Mucho appreciated. – WhozCraig Dec 20 '13 at 23:26
2

If you initialise it to null and then immediately assign some other value to it, or if you assign null to it (after deletion) and then immediately let it go out of scope, it's pretty pointless.

However, if there's any chance that some other code might want to use the object it's pointing at while the pointer still exists and the object may not exist, then you will want to be able to signify to that code that nothing is there. If the pointer is set to null, the code can check for null before attempting to dereference the pointer.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
1

There is no benefit from an optimising compiler's point of view: the redundant stores will be eliminated. Modern compilers will be able to see that the value isn't used and remove them.

There may be benefit from the human reader's point of view: it may make the code easier to understand and may help reduce bugs caused by using uninitialised or freed data. In some cases initialising to NULL can actually hide issues, though, as most compilers will warn if you try to use a value without initialising it first.

My personal opinion though is that you should initialise the variable properly with its final value as close to declaring it as possible and let the compiler warn you if you miss an execution path, then you shouldn't be able to use a variable once its value has been freed because it's also gone out of scope. Freeing data using smart pointers helps here.

Andrew Aylett
  • 39,182
  • 5
  • 68
  • 95
1

Just to clarify the other answers, if you attempt to write to or read from memory referred to by an uninitialized pointer, or a pointer referring to memory that has been deleted or freed, the program may not crash, or may crash long after the write/read, making it hard to find the bug.

If you do the same with a null pointer, the program will (probably) crash immediately, making debugging easier.

Andrey Mishchenko
  • 3,986
  • 2
  • 19
  • 37
1

It is good coding practice to always initialize your pointers to something. In C++, the value of an uninitialized pointer is undefined, so if you have a single line like:

int* p;

p takes on the value of whatever happened to be in the memory p takes up (not what it points to, but the memory for the pointer value itself). There are times when it makes sense to initialize a pointer to NULL, but that really depends on your code.

As for setting NULL after deletion, it's a habit a few people follow. The benefit is that you can call delete on NULL without problems, whereas a double delete on a pointer could cause undefined behavior. Before the idea of RAII was popular, some people followed the "better safe than sorry" method of calling delete on multiple code paths. In those cases, if you don't set pointer to NULL, you might accidentally delete a pointer twice, so setting it to NULL mitigates that problem. Personally, I think it's a sign of poor design if your pointers don't have proper ownership, and you have to guess at when to call delete.

geoffliu
  • 510
  • 3
  • 10
  • 2
    Deleting memory twice is not the only problem it solves. If `p == nullptr`, and you attempt to use `p`: `*p = 42;`, you will get a runtime exception immediately. If `p` is a "valid" address and you modify it, you could be squashing memory that has been reallocated as something else and will have a very hard to find bug. – Zac Howland Dec 20 '13 at 20:41
0

On a modern hardware and operating system, a null pointer is an invalid pointer. Therefore, when you try to access it then your program will be shutdown by either your hardware or your operating system. This can help as it will guarantee that you your program will not attempt to access some memory that has been freed earlier and cause undefined behavior and get away with it.

It can also help with debugging, as you can then see if that memory has been freed at your breakpoint.

But ideally, a good C++ programmer should trie to avoid using raw pointers and use RAII when ever possible.

Caesar
  • 9,483
  • 8
  • 40
  • 66
0

Initializing a pointer to NULL/nullptr, in any context, is a generally idea because dangling pointers can refer to actual memory. If you nullify a pointer after its use and you dereference it, modern platforms will usually crash cleanly.

Setting a pointer to null after you're done with it can be a good idea for the same reason, but I personally don't think that it's especially useful if you're not keeping the variable around, like when it's a local variable.

Even better practice, though, is to avoid raw pointers altogether. C++11 provides unique_ptr, shared_ptr and weak_ptr (in <memory>) that wrap pointers with those three semantics. Using them, you never need to delete anything manually and you almost never need to set anything to nullptr yourself.

zneak
  • 134,922
  • 42
  • 253
  • 328