1

I'm trying to understand exactly what happens to deleted variables in c++. Let's say I have something like the following.

MyObject * obj;

for (int i = 0; i < 100000000; i++){
    obj = someMethodThatReturnsNewMyObject();
    obj->doSomething();
    delete obj;
}

Now, upon instantiation, obj is a pointer to a MyObject object. It is first initialized by the line obj = someMethodThatReturnsNewMyObject();. Then some method is called just for fun, and obj is deleted. Now I know when something is deleted like this, the memory space that it is pointing to is expunged, and the pointer is set to point an nothing.

But, then when the for loop comes back around, I re-initialize the pointer, causing it to allocate a new memory space and obj then points at this new space instead. But, at no point was the pointer itself removed from memory. Throughout the loop it only ever points at whatever I tell it to point to or points at nothing (upon deletion).

My question then, is this: When does the pointer itself, that is, the memory space taken up by the pointer, get deleted and why is it not under my requirements to have to delete that if I am required to delete the memory pointed at?

zephyr
  • 2,182
  • 3
  • 29
  • 51
  • 1
    automatic storage duration. variables go out of scope at the end of their block. In real life, they come off the stack at the end of the function. – Ryan Haining May 20 '15 at 18:56
  • 2
    Obligatory: in modern C++, if you have `delete` in application code, you are doing it wrong. Use `shared_ptr` and `unique_ptr` (or other smart pointers), and let them delete the object when they go out of scope (and if deletion is appropriate). This is called RAII. – hyde May 20 '15 at 18:57
  • Please read any book of any programming language regarding pointers. (or have a video: https://www.youtube.com/watch?v=i49_SNt4yfk) –  May 20 '15 at 18:58
  • "and the pointer is set to point an nothing" That doesn't happen automatically. You don't really need it here, but you should add `obj = NULL;` at the end of the loop after the delete. – IronMensan May 20 '15 at 18:58
  • 2
    Your assumptions are a bit off. The `delete` function does not "set to point to nothing". The `delete` call does not touch the value of `obj` at all. It still points to the same memory location. The difference is though that it points to an /unallocated/ memory location, and trying to access it may lead to unexpected errors. Thus subsequently overriding `obj` with a new value is perfectly ok. – Dov Grobgeld May 20 '15 at 18:58
  • the function `someMethodThatReturnsNewMyObject` can't return an *object* as that would not compile. It must return a *pointer* to an object. – Felix Glas May 20 '15 at 18:59
  • So why does this apply to the pointer, and not the memory pointed at, if that memory was created in the same scope as the pointer? If I remove the `delete`, I get a memory leak, and going out of scope does not automatically delete all the allocations of new `MyObject` objects. – zephyr May 20 '15 at 18:59
  • the memory is allocated dynamically at run time, it's not allocated in the function's callstack, it's elsewhere on the heap. – Ryan Haining May 20 '15 at 19:00
  • http://stackoverflow.com/questions/22146094/why-should-i-use-a-pointer-rather-than-the-object-itself?rq=1 – Felix Glas May 20 '15 at 19:04
  • @zephyr The purpose of heap is, you can have persistent objects there. Raw pointer does not keep track of other pointers pointing to same object, so a pointer going out of scope doesn't say anything about the the memory it points to needing to be deleted. You need to (and *should*) wrap the raw pointer in a smart pointer of right type to achieve automatic, safe deletion. – hyde May 23 '15 at 09:18

6 Answers6

5

The pointer (the variable obj) has automatic storage duration – just like the variable i. The compiler will emit code to automatically allocate memory for such a variable and release it when it goes out of scope; after invoking any destructor. This memory will come from the stack at run-time, which makes it extremely fast to allocate and free.

By the way, calling delete obj does not “set the pointer to point to nothing”. At least if you mean by this that the pointer is modified. It will continue to have whatever value it had before but that value will no longer point to a valid memory location.

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • 1
    Thanks, that helps. I was mis-remembering about what delete actually did and thought it also set the pointer to nothing. I think I was remembering the tandem commands `delete obj` and `obj = NULL`. – zephyr May 20 '15 at 19:04
  • Yes, that (`delete obj; obj = NULL;`) was a common idiom in older C++ code though I never liked it. In modern code, you shouldn't see it any more due to the pervasive use of smart pointers (which, internally, will do exactly that, of course). – 5gon12eder May 20 '15 at 19:07
2

Now I know when something is deleted like this, the memory space that it is pointing to is expunged,

What the run time environment does with the memory is not specified by the language. The language only specifies that using that memory is undefined behavior.

and the pointer is set to point an nothing.

That is not correct. The value of the pointer remains what it was. It points to memory that is not valid any more.

When does the pointer itself, that is, the memory space taken up by the pointer, get deleted

It's implementation specific. In common implementations, the memory gets reclaimed by the run time environemnt when the function returns. As per the language, the life of the pointer ends when the scope in which it is defined ends. Using the memory occupied by the pointer after its scope has ended is undefined behavior.

If you had:

MyObject** ptr = NULL:
for (int i = 0; i < 100000000; i++){

    // obj is defined in the scope of the for loop.
    // It's life ends when the for loop ends.
    MyObject* obj = someMethodThatReturnsNewMyObject();

    obj->doSomething();
    delete obj;

    // Make ptr point to the address of obj.
    ptr = &obj;
}

*ptr = NULL;  // This is undefined behavior since ptr
              // points to memory that is not valid any more.
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

The pointer itself gets deleted when the program terminates. You're probably not being required to delete the pointer itself because you're reusing it, and it occupies the same amount of space in memory for the duration of its existence. The memory being pointed to, however, is being recycled with each iteration of your loop in order to keep from filling your memory up. This wouldn't be a problem if your for loop only runs a few times, but if you're looping a lot without de-allocating that space it could potentially fill up your memory and crash your program.

Jim Stitzel
  • 121
  • 4
1

The delete keyword deletes the memory that a pointer points to. It does not delete the pointer itself.

How a pointer is deallocated depends on where it is declared. If your example code is in a method/function, it gets declared on the stack and is released when the method/function returns. If the pointer is a global variable, then it would live the life of your program.

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
1

the memory space that it is pointing to is expunged, and the pointer is set to point an nothing.

Forgiving the typo, the pointer is not changed. It still points to where the object was before delete was called. After deletion, using the object through the pointer is "bad". It might work and access the previous content. It might access total garbage (like from memory reuse). Calling methods through the pointer could well jump into space, hopefully segfalting instead of reformatting your disks.

You do want the pointer variable to remain. It gets used each iteration. delete is useful to free the memory (and run any destructors) in the object a pointer points to.

wallyk
  • 56,922
  • 16
  • 83
  • 148
1

when you do : delete obj

Then you are marking the memory location pointed by obj to be deleted and will be returned to the system. Its a bit tricky here larger chucks are mmap'd and smaller ones are managed by heap and deleting it will not be reflected in the system unless it is the topmost. If it is not the topmost in the heap, then brk/sbrk will not be moved and that will be reused when you next ask/allocate a size same or smaller than then one that is marked to be deleted. The algorithm is bit more complicated but that is the gist.

In your code, in the second iteration obj can point to a entirely different chunk/block.

resultsway
  • 12,299
  • 7
  • 36
  • 43