Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does 'delete pointer' simply mean '*pointer = 0'?

# 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)

like image 723
Avinash Sonawane Avatar asked Jan 31 '12 01:01

Avinash Sonawane


People also ask

What does it mean to delete a pointer?

Deleting a pointer (or deleting what it points to, alternatively) means delete p; delete[] p; // for arrays. p was allocated prior to that statement like p = new type; It may also refer to using other ways of dynamic memory management, like free free(p); which was previously allocated using malloc or calloc.

Does delete also delete the pointer?

Yes, it destroys the object by calling its destructor. It also deallocates the memory that new allocated to store the object. Or does it only destory the pointer? It does nothing to the pointer.

Is delete same as nullptr?

@Omega delete pointer; pointer = nullptr. just deletes the pointer. setting it to null after deleting is fine. Setting null to a pointer is not same as deleting.

What happens when you delete a pointer?

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).


3 Answers

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).

like image 101
justin Avatar answered Nov 14 '22 23:11

justin


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."

like image 30
Nicol Bolas Avatar answered Nov 14 '22 23:11

Nicol Bolas


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.

like image 24
Michael Burr Avatar answered Nov 14 '22 21:11

Michael Burr