Does 'delete pointer' simply mean '*pointer = 0'?
Asked Answered
W

5

5
# include <iostream>

int main()  
{  
using std::cout;
int *p= new int;

*p = 10;
cout<<*p<<"\t"<<p<<"\n";
delete p;
cout<<*p<<"\t"<<p<<"\n";

return 0;

}

Output:
10 0x237c010
0 0x237c010

Here after deleting p, why the pointer p retains its value? Doesn't delete frees the pointer p?
What exactly is meant by 'freeing the pointer'?
Does 'delete p' simply mean '*p = 0'?(which seems from the output)

Womanize answered 31/1, 2012 at 1:33 Comment(2)
Well, it at least also deletes the data pointed to by the pointer, but I'm sure someone will have a much better answer shortly about what "deleting" memory actually means. I suspect it may not even zero the memory, but rather just allow that space to be allocated again.Tourniquet
Use a bit of critical thinking -- how would *p = 0 even work for e.g. std::string?Poppy
F
6

Here after deleting p, why the pointer p retains its value?

It's how the language is designed. If you want the pointer you hold to be zeroed, you'll need to assign it zero yourself. The pointer p is another piece of memory, separate from the allocation/object it points to.

Doesn't delete frees the pointer p?

It calls the destructor the object and returns the memory to the system (like free). If it is an array (delete[]), destructors for all elements will be called, then the memory will be returned.

What exactly is meant by 'freeing the pointer'?

When you want a piece of memory from the system, you allocate it (e.g. using new). When you are finished using it, you return it using the corresponding free/delete call. It's a resource, which you must return. If you do not, your program will leak (and nobody wants that).

Fermata answered 31/1, 2012 at 1:35 Comment(4)
@Justin- Will you please explain why the pointer p has retained its value in above code even after deleting?Womanize
@Avinash : Why should deallocating memory change its contents?Poppy
@AvinashSonawane - note that it is not safe to access data after it has been deleted, even though it may maintain its original value directly after the delete.Tourniquet
@AvinashSonawane: See my favorite answer on the site for details. Accessing memory you have deallocated is no different than accessing a pointer to a variable that is out of scope.Malt
M
2

In order to understand what freeing memory means, you must first understand what allocating memory means. What follows is a simplified explanation.

There exists memory. Memory is a large blob of stuff that you could access. But since it's global, you need some way to portion it out. Some way to govern who can access which pieces of memory. One of the systems that governs the apportionment of memory is called the "heap".

The heap owns some quantity of memory (some is owned by the stack and some is owned by static data, but nevermind that now). At the beginning of your program, the heap says that you have access to no heap-owned memory.

What new int does is two fold. First, it goes to the heap system and says, "I want a piece of memory suitable to store an int into." It gets back a pointer to exactly that: a piece of the heap, into which you can safely store and retrieve exactly one value of type int.

You are now the proud owner of one int's worth of memory. The heap guarantees that as long as its rules are followed, whatever you put there will be preserved until you explicitly change it. This is the covenant between you and the almighty heap.

The other thing new int does is initialize that piece of the heap with an int value. In this case, it is default initialized, because no value was passed (new int(5) would initialize it with the value 5).

From this point forward, you are legally allowed to store exactly one int in this piece of memory. You are allowed to retrieve the int stored there. And you're allowed to do one other thing: tell the heap that you are finished using that memory.

When you call delete p, two things happen. First, p is deinitialized. Again, because it is an int, nothing happens. If this were a class, its destructor would be called.

But after that, delete goes out to the heap and says, "Hey heap: remember this pointer to an int you gave me? I'm done with it now." The heap system can do whatever it wants. Maybe it will clear the memory, as some heaps do in debug-builds. In release builds however, the memory may not be cleared.

Of course, the reason why the heap can do whatever it wants is because, the moment you delete that pointer, you enter into a new agreement with the heap. Previously, you asked for a piece of memory for an int, and the heap obliged. You owned that memory, and the heap guaranteed that it was yours for as long as you wanted. Stuff you put there would remain there.

After you had your fun, you returned it to the heap. And here's where the contract comes in. When you say delete p, for any object p, you are saying the following:

I solemnly swear not to touch this memory address again!

Now, the heap might give that memory address back to you if you call new int again. It might give you a different one. But you only have access to memory allocated by the heap during the time between new and delete.

Given this, what does this mean?

delete p;
cout << *p << "\t" << p << "\n";

In C++ parlance, this is called "undefined behavior". The C++ specification has a lot of things that are stated to be "undefined". When you trigger undefined behavior anything can happen! *p could be 0. *p could be the value it used to be. Doing *p could crash your program.

The C++ specification is a contract between you and your compiler/computer. It says what you can do, and it says how the system responds. "Undefined behavior" is what happens when you break the contract, when you do something the C++ specification says you aren't supposed to. At that point, anything can happen.

When you called delete p, you told the system that you were finished using p. By using it again, you were lying to the system. And therefore, the system no longer has to abide by any rules, like storing the values you want to store. Or continuing to run. Or not spawning demons from your nose. Or whatever.

You broke the rules. And you must suffer the consequences.

So no, delete p is not the equivalent of *p = 0. The latter simply means "set 0 into the memory pointed to by p." The former means "I'm finished using the memory pointed to by p, and I won't use it again until you tell me I can."

Malt answered 31/1, 2012 at 2:6 Comment(0)
N
1

Here after deleting p, why the pointer p retains its value? Doesn't delete frees the pointer p?

It frees the memory the pointer points to (after calling any appropriate destructor). The value of the pointer itself is unchanged.

What exactly is meant by 'freeing the pointer'?

As above - it means freeing the memory the pointer points to.

Does 'delete p' simply mean '*p = 0'?(which seems from the output)

No. The system doesn't have to write anything to the memory that's freed, and if it does write something it doesn't have to write 0. However, the system does generally have to manage that memory in some way, and that might actually write to the area of memory that the pointer was pointing to. Also, the just-freed memory can be allocated to something else (and in a multi-threaded application, that could happen before the delete operation even returns). The new owner of that memory block can of course write whatever they want to that memory.

A pointer that is pointing to a freed block of memory is often known as a 'dangling' pointer. It is an error to dereference a dangling pointer (for read or write). You will sometimes see code immediately assign a NULL or 0 to a pointer immediately after deleting the pointer, sometimes using a macro or function template that both deletes and clears the pointer. Note that this won't fix all bugs with dangling pointers, since other pointers may have been set to point to the memory block.

The modern method of dealing with these kinds of problems is to avoid using raw pointers altogether in favor of using smart pointers such as shared_ptr or unique_ptr.

Newmark answered 31/1, 2012 at 1:54 Comment(0)
S
0

delete p simply frees the memory allocated during a call to the new operator. It does not change the value of the pointer or the content of the deallocated memory.

Sang answered 31/1, 2012 at 1:37 Comment(4)
delete ensures that the destructor is called, which may change the value of the pointer or the content of the deallocated memory.Bambara
@Narrakan- If there is no change in the pointer value nor in the pointed value then what exactly is achieved by freeing the memory ? Since pointer value is not changed anybody can simply access that 'deleted' object.Womanize
@AvinashSonawane well, as you have seen by yourself, you can access *p even after you deleted it, so you can still access that memory, though it is undefined behaviour.Sang
@Avinash The freed memory is returned to the heap, and can then be used to allocate other objects. If you do not recycle freed memory in this way, then the application's memory consumption will grow continuously until it crashes. If the application is, say, an embedded device controlling an aircraft engine, then the aircraft will crash also.Unproductive
P
0

(Note the following isn't how it actually works so take it with a grain of salt.)

Inside the implementation of new it keeps a list of all available memory when you said "int *p= new int;" it cut a int sized block off of its list of available memory and gave it to you. When you run "delete p;" it gets put back in the list of available memory. If your program called new 30 times without calling delete at all you would get 30 different int sized chunks from new. If you called new then delete 30 times in a row you might (but not necessarily) get the same int sized block. This is because you said you weren't using it any more when you called delete and so new was free to reuse it.

TLDR; Delete notifies new that this section of memory is available again it doesn't touch your variable.

Punchdrunk answered 31/1, 2012 at 1:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.