Unexpected behavior after deleting a pointer in a vector

I experimented with pointer vectors and came across the following behavior, which I don't quite understand:

#include <iostream> #include <vector> int main() { std::vector<int*> vec; int* p1 = new int; *p1 = 100; vec.push_back(p1); std::cout << *vec[0] << std::endl; delete p1; std::cout << *vec[0] << std::endl; int* p2 = new int; *p2 = 200; std::cout << *vec[0] << std::endl; return 0; } 

Using the MinGW C ++ compiler (g ++), this gave me the following result:

 100 5640648 200 

Now, of course, the actual element vec[0] not deleted when the pointer was deleted, but note that p2 is not inserted into the vector at all. However, printing the value of the first element returns the value of this seemingly unbound pointer! Also, restructuring the code a bit to declare p2 before removing p1 does not give this behavior.

Just to make sure, I also compiled this with MSVC ++, which gave me the following (expected) output:

 100 5484120 5484120 

Does anyone have an explanation for the first exit?

+4
source share
5 answers

He redistributed the space held by p1 , which vec[0] was still indicating, hence the value 200 appeared.

As you noticed, this was the behavior of one compiler, and the other compiler acted differently. You may have other types of behavior based on different optimization switches. In general, the behavior is undefined, although sometimes we can find out what happened in individual cases.

+5
source

because after deletion, you gain access to memory, which causes undefined behavior:

 delete p1; std::cout << *vec[0] << std::endl; <-- Buggy code 

undefined: - It is not guaranteed how it will work

+6
source

Do you understand why this is undefined behavior in the first place?

The value of vec[0] is p1 . As soon as you delete p1; it becomes illegal to dereference vec [0]. vec [0] is just a copy of your p1 pointer.

Suppose the p1 (address) value of 953241, which is returned new to you, is free to use. The int value that you store in this address is 100. But as soon as you delete p1, you waive any rights regarding that address. You effectively give it to the system. You can no longer read.

0
source

When you delete p1 , C ++ frees up the space that p1 took up the heap and allows it to be used for other data. Therefore, when you create p2 , it puts it there, because this is the next place in memory that it wants to use.

vec[0] stays there only because the data from your pointer is still on the stack. (C ++ does not know that you deleted the pointer, but the pointer data will not go anywhere, so you can access it. It will be replaced the next time you do something on the stack.)

I assume that MSVC ++ purposefully tries not to use the newly freed memory space, because it is β€œsafer” - if you deleted something by accident, and then overwritten it, it disappeared forever.

0
source
 delete p1; std::cout << *vec[0] << std::endl; // (1.) int* p2 = new int; *p2 = 200; std::cout << *vec[0] << std::endl; // (2.) return 0; 
  • You deleted the memory so that it was not determined what would be at this address.
  • in g++ output you will see that the new value 200 is displayed, this is because it is located at

     int* p1 = new int; *p1 = 100; 

    do not use this value because the behavior is implementation-specific and it is displayed only because you are not allocating anything earlier that might fit in a freed memory cell.

0
source

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


All Articles