15
void doSomething()
{  
    TheObject *ptr = new TheObject;
    delete ptr;
    ptr = NULL;
    return 0;
}

Let me borrow the words from operator delete in cplusplus.com:

Deallocates the memory block pointed by ptr (if not null), releasing the storage space previously allocated to it by a call to operator new and rendering that pointer location invalid.

Please help to clear my confusions: what happens to the pointer itself after delete? The pointer itself does have an address, right? So after the pointed block is deleted, what about the pointer itself?

Could I say that the pointer itself will be free after returning the method where the pointer is initialized? Is the pointer itself placed on the stack or heap?

Honest Abe
  • 8,430
  • 4
  • 49
  • 64
Stephen Kuo
  • 1,175
  • 3
  • 11
  • 19

3 Answers3

30

The pointer itself does have an address and the value. The address of the pointer does not change after you perform delete on it. The space allocated to the pointer variable itself remains in place until your program releases it (which it might never do, e.g. when the pointer is in the static storage area). The standard does not say what happens to the value of the pointer; all it says is that you are no longer allowed to use that value until you assign your pointer a valid value. This state of the pointer is called dangling.

In your program, the pointer ptr is dangling after delete has completed, but before the ptr = NULL assignment is performed. After that it becomes a NULL pointer.

The pointer it self is placed on stack or heap?

Pointer variable is a regular variable. Its placement follows the same rules as the placement of other variables, i.e. you can put a pointer in a static area, in an automatic area (commonly known as "the stack") or in the dynamic memory (also known as "the heap"). In this case, you allocate a pointer to a pointer:

TheObject **ptrPtr = new TheObject*; // The pointer to a pointer is on the stack
*ptrPtr = new TheObject;             // The pointer to TheObject is in the heap
delete *ptrPtr; // The space for TheObject is released; the space for the pointer to TheObject is not
delete ptrPtr;  // Now the space for the pointer to TheObject is released as well
// The space for the pointer to pointer gets released when ptrPtr goes out of scope
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • *"Neither of them changes when you perform a `delete` on the pointer"* I don't think the standard provides such a guarantee. – user541686 May 13 '14 at 02:14
  • @dasblinkenlight If we create lots of pointers and then delete them, any chance we get "out of memory" since the pointer itself is not released? – Stephen Kuo May 13 '14 at 02:26
  • 1
    @dasblinkenlight: No, `operator delete(p)` and `delete p` are different beasts. – user541686 May 13 '14 at 02:43
  • @dasblinkenlight Maybe I did not catch you correctly. **The pointer itself does have an address and the value. Neither of them changes when you perform a delete on the pointer - the space allocated to the pointer variable remains in place until your program releases it**. `delete` the pointer does not delete the pointer itself, if it is, ex: `for (xxx) {TheObj *ptr0 = new TheObj; delete ptr0; TheObj *ptr1 = new TheObj; delete ptr1; // and ptr2, ptr3, ptr4 ....}` what about the address of all the ptrs themselves? Does compiler allow us to reuse the address(memory) of the pointer itself? – Stephen Kuo May 13 '14 at 03:00
  • 2
    @Stephen: You're allowed to *assign* a new value to the pointer, but you're not allowed *read* the old value. This is true for *every* pointer that had that old value, not just that particular pointer -- they are *all* invalidated when `delete` is called on the pointer. – user541686 May 13 '14 at 03:21
  • @Stephen: I hope you realize the answer you accepted is incorrect! – user541686 May 13 '14 at 05:39
  • Seems that I see a point that helps me to understand: **The space for the pointer to pointer gets released when ptrPtr goes out of scope**, like what @Tristan Brindle pointed out. – Stephen Kuo May 13 '14 at 10:04
  • @dasblinkenlight: I think you still don't get it. *"you are no longer allowed to use that value like a pointer until you assign your pointer a valid value"*... the phrase "like a pointer" is very ambiguous and I feel you still don't understand what we're trying to say. You may *not* even ***read*** the pointer *itself*, is the problem. Reading the value is something you can do with *any* variable, not just a pointer. The fact that you say "like a pointer" means you still don't understand where the problem is. – user541686 May 13 '14 at 11:30
  • @Mehrdad "You may not even read the pointer itself, is the problem." Your understanding is wrong: you can most definitely read the value of that pointer, as long as you do not dereference it, or pass it to a deallocation function. What you get back from the read is implementation-defined. The standard is very specific on that: "Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. **Any other use of an invalid pointer value has implementation-defined behavior.**" (3.7.4.2.4) – Sergey Kalinichenko May 13 '14 at 11:56
  • 1
    @dasblinkenlight: If reading a pointer is implementation-defined then that means it could trap on a particular implementation. So you can't rely on it without knowing the particular implementation, which we don't here. – user541686 May 13 '14 at 21:02
  • @Mehrdad I am no longer sure what are we arguing about here. If there a statement that you would like to dispute in my edited answer above, please let me know, or better yet, suggest an edit. – Sergey Kalinichenko May 13 '14 at 21:07
  • @dasblinkenlight: Take out the phrase *"like a pointer"* and it should be fine. – user541686 May 13 '14 at 21:16
  • @Giorgi I think this is an interesting question, so you may want to ask it as a question, not as a comment. The fact that a pointer has been previously deleted does not matter here; the real issue would be "is printing a pointer set to an arbitrary numeric value with `%p` an undefined behavior?" – Sergey Kalinichenko Oct 28 '15 at 15:13
4

In C and C++, a pointer can be thought of in many ways as just an integer in disguise. So when you say:

TheObject *ptr = new TheObject;

Then ptr is just like a stack-allocated ("automatic") integer variable, one that happens to be big enough to hold the memory address of the heap-allocated TheObject. It's similar to saying

size_t i = /* some value given to you by the runtime */.

Later on, when you write

ptr = NULL;

it has an identical meaning to:

i = 0;

So what happens to the pointer when you leave the function? Just as with any other automatic variable, it's deallocated at the end of the block. It's as simple as that. (Of course, the thing that's pointed to will live on until you call delete, or free() in C.)

Tristan Brindle
  • 16,281
  • 4
  • 39
  • 82
2

Performing delete invalidates the pointer (see [new.delete.single]#10). It could be said that the value is changed: previously it had a value, but now it does not have a value.

Trying to read the value of the pointer (note: this is different to dereferencing it) causes implementation-defined behaviour since C++14, which may include generating a runtime fault. (In C++11 and older standards, it was undefined behaviour). Ref: [basic.stc.dynamic.deallocation]#4.

It would be legal for the compiler to also set the pointer to be null, or set it to some recognizable garbage for debugging purposes (although I don't know of any compilers that do this).

M.M
  • 138,810
  • 21
  • 208
  • 365
  • You can `access` the value of a pointer all the time, e.g write access with `x = 0;`. But you should only `dereference` the pointer only when it is valid. In that case you don't access not only the pointer (read access) but you will also access the value where the pointer points to. Could you improve your answer to make this clear? – harper May 13 '14 at 03:37
  • By "access the value" I meant read access, will update to clarify. – M.M May 13 '14 at 03:51
  • of course reading `*x` is undefined, after `x` is deleted. Your answer is not clear, are you saying reading `x` or `*x` is undefined? – PoweredByRice Apr 20 '17 at 01:53
  • @PoweredByRice reading `x` is implementation-defined. I hoped that saying "read the value of the pointer (note: this is different to dereferencing it)" makes that distinction clear – M.M Apr 20 '17 at 02:20
  • 1
    @M.M _"Trying to read the value of the pointer (note: this is different to dereferencing it) causes implementation-defined behaviour since C++14, which may include generating a runtime fault. (In C++11 it was undefined behaviour)."_ AFAIK there never was (and will be) UB with copying pointer values, deleted or not. You've seem to have posed som misconception with that: https://stackoverflow.com/questions/44182049/pointers-in-c-after-delete – πάντα ῥεῖ May 25 '17 at 14:06
  • @πάνταῥεῖ see answer by "Mankarse" on that thread (which is basically my answer here with text from my references inserted) – M.M May 25 '17 at 21:10
  • @M.M I alread marked the whole thing as dupe, for sake of clarit. – πάντα ῥεῖ May 25 '17 at 21:12