Pointer and dynamic memory allocation

My question is:

int* x = new int; cout << x<<"\n"; int* p; cout << p <<"\n"; p = x; delete p; cout << p <<"\n"; 

I wrote this on my own to understand the pointer and understand (also get lost) the dynamic new and delete .

My Xcode can compile the program and return the following results:

  0x100104250 0x0 0x100104250 

I know that I can only call delete in dynamically allocated memory. However, I called delete in p in the above program and compiles.

Can anyone explain this to me? Why can I remove p ?

In addition, I found that the program has changed to the following:

  int* x = new int; int* p; cout << p <<"\n"; delete p; cout << p <<"\n"; 

Then my Xcode compiles again and returns me:

  0x0 0x0 Program ended with exit code: 0 

and now I'm completely lost :(. Can someone explain this to me? Why could I remove p since it has nothing to do with x ?


Since Xcode compiles successfully, I assume that the above two programs are correct for the computer. However, I think this is again the statement "just deleting a call in dynamic allocated memory". Or, perhaps, I did not quite understand what a pointer is and what dynamic allocated memory is. I found this post when I searched on the Internet. But I don’t think it looks like my business.

Please help me.


I would like to ask one more question. The code here is about a binary search tree. From line 28-32, he deals with deleting the node with one child. Here I put this piece of code if the web link is not working.

else if (root-> left == NULL) {struct node * temp = root; root = root-> right; delete temp; }

It is these codes that prompt me to ask a question regarding the pointer. After the response given by this message. Is it correct to understand the code as follows?

I cannot first bind the parent node to the root with the right child of the root. and then remove the root of the node, since the subtree under the root of the node will also be deleted. So I have to create a temp pointer that points to the memory slot that root points to. Then I will connect the parent node with the root with the root to the right of root. and now I can safely remove the memory slot pointed to by β€œroot” (ie the pace, since both point to the same memory). This way I free up memory and also keep the connection between parent and child. In addition, the pace is still present and still points to β€œthis” memory slot. Should I set it to NULL after uninstall?

Thanks to everyone in advance.

Yaofeng

+5
source share
4 answers

Yes, you can only call delete in the memory that was allocated through new . Note that this is the memory address (the value of the pointer), not the variable holding the pointer. So your first code is:

 int* x = new int; //(A) cout << x<<"\n"; int* p; cout << p <<"\n"; p = x; //(B) delete p; //(C) cout << p <<"\n"; //(D) 

Line (A) dynamically allocates memory at some address ( 0x100104250 in your output example) and stores this address in the variable x . The memory is allocated through new , which means that delete must be called at 0x100104250 .

Line (B) assigns address 0x100104250 (value of pointer x ) to pointer p . Line (C) then calls delete p , which means "free the memory pointed to by p ". This means that it calls delete at 0x100104250 , and all is well. Memory at 0x100104250 was allocated through new , and therefore not correctly allocated through delete . The fact that you used another variable to store the value does not matter.

Line (D) simply prints the pointer value. delete affects the memory pointed to by the pointer, not the pointer itself. The pointer value remains unchanged - it still points to the same memory that the memory is no longer allocated.


The second example is different: you call delete p when p not initialized with anything. It points to a random chunk of memory, so calling delete on it is, of course, illegal (technically, it has an "Undefined Behavior" and most likely a failure).

It seems that in your specific example, you start the debug assembly, and your compiler β€œhelps” initialize local variables to 0 if you do not initialize them yourself. Thus, this actually leads to the fact that your second example does not fail, since the delete call on the null pointer is valid (and does nothing). But the program does have an error, since local variables are usually not initialized implicitly.

+2
source
 p = x; 

This would mean that p contains the same value as x ( p would point to the same object as x ). So basically when you say

 delete p; 

Deletion is performed at the address indicated by p , which is similar to address x . Therefore, this is perfectly true, since the object referenced by this address is allocated using new .

Second case: -

Concomitantly, your p pointer is set by the compiler as a NULL pointer (you should not depend on this). Thus, deleting this pointer is safe. If it were not a NULL pointer, you might see a failure.

+1
source

Ok, look at the documentation for the delete operator. According to http://en.cppreference.com/w/cpp/memory/new/operator_delete :

Called by delete-expression to free memory previously allocated to a single object. The behavior of the standard library implementation of this function is undefined if ptr is not a null pointer or is a pointer previously obtained from the standard library implementation of the new (size_t) operator or the new (size_t, std :: nothrow_t) operator library.

So, the following happens: you invoke a new statement that allocates sizeof (int) bytes for the int variable in memory. This part in memory refers to your x pointer. Then you create another pointer p that points to the same memory address. When you call delete, the memory is released. Both p and x still point to the same address , except that the value in this place is now garbage. To make this clear, I changed the code as follows:

 #include <iostream> using namespace std; int main() { int * x = new int; // Allocate sizeof(int) bytes, which x references to *x = 8; // Store an 8 at the newly created storage cout << x << " " << *x << "\n"; // Shows the memory address x points to and "8". (eg 0x21f6010 8) int * p; // Create a new pointer p = x; // p points to the same memory location as x cout << p << " " << *p << "\n"; // Shows the memory address p points to (the same as x) and "8". delete p; // Release the allocated memory cout << x << " " << p << " " << *x << " " << *p << "\n"; // p now points to the same memory address as before, except that it now contains garbage (eg 0x21f6010 0) return 0; } 

After starting, I got the following results:

 0x215c010 8 0x215c010 8 0x215c010 0x215c010 0 0 

So remember that with delete, you free up memory, but the pointer still points to the same address. Therefore, generally safe practice also sets a pointer to NULL. Hope this is a little better now :-)

+1
source

Before answering, you need to understand the following points.

  • once you delete pointer, it does not need to be assigned 0 . It could be anything.
  • You can remove 0 or NULL without any harm.
  • Undefined behavior is what can happen. the program may crash, it may work fine, as if nothing had happened, it may lead to some random results, etc.,

However, I called delete on p in the above program and compiles.

Can anyone explain this to me? Why can I remove p?

This is because you assigned the memory address allocated by new through x . ( p = x; ) x (or p ) is a valid memory address and can be deleted.

Now x is called the Hanging Pointer . Because it indicates a memory that is no longer valid. Access to x after deletion is undefined behavior.

Can someone explain this to me? Why can I remove p since it has nothing to do with x?

This is because your p to 0. Therefore, you avoid undefined behavior. However, it is not guaranteed that your uninitialized pointer will be 0 or NULL . This works fine right now, but you are wading through undefined behavior here.

0
source

Source: https://habr.com/ru/post/1208562/


All Articles