Delete behavior []

Possible duplicate:
C ++ delete - deletes my objects, but can I still access the data?

I am wondering why I am getting the following behavior with the following (rather contrived) code. I am using gcc 4.4.5 on Ubuntu 10.10

#include <iostream>

int main(int argc, char *argv[])
{
  int N = 5;
  int *myarr = new int[N];//create an integer array of size 5

  for (int i = 0; i < N; ++i)
    {
      myarr[i] = 45;
      std::cout << myarr[i] << std::endl;
    }  


  delete[] myarr;//kill the memory allocated by new
  std::cout << "Let see if the array was deleted and if we get a segfault \n" ;

  for (int i = 0; i < N; ++i)
    {
      std::cout << myarr[i] << std::endl;
    }


  return 0;
}

      

The code compiles even with the flag -Wall

. Output signal

Desktop: ./a.out
45
45
45
45
45
Let see if the array was deleted and if we get a segfault 
0
0
45
45
45
Desktop: 

      

Why myarr

can the array be accessed as if it were ever deleted without a segfault? Further, even if the array myarr

was deleted, since the values ​​45 still appear to be printed correctly at positions 2,3 and 4.

In short, what is doing here delete[]

?

+3


source to share


7 replies


delete[]

calls the destructor for each element of the array and tells your computer that you will no longer use memory. The memory still exists, you are simply not allowed to use it.



What you are seeing is undefined behavior. This can fail in a number of ways, but since your program is so short, it will probably work as you saw most of the time.

+3


source


Free memory does not guarantee that you will get a segfault if you later try to access that memory. Basically, accessing memory after freeing it leads to undefined behavior - anything can happen.



In your case, the operator delete[]

frees the memory and returns it to your runtime library. However, the runtime library hangs in memory and does not immediately return it to the OS (after all, you may need it again pretty soon). The runtime library will manage its own data structures using memory that your application has already freed up. For example, the zeros you see may be part of a loose list structure.

+2


source


The operator delete[]

releases memory only. Memory access after delete[]

has undefined behavior.

The memory marked myarr

will probably still contain the values ​​you assigned for a while. This memory address will keep the same values ​​until someone writes anything.

+1


source


The memory has been freed up and some have been wiped out, as you can see. It can still be obtained, but the fact that your program is not crashing is mainly due to the fact that not enough time has passed for this memory to be allocated for different objects, or that you have not tried doing anything naughty with it. for example using the value inside it as an offset for the buffer or whatever.

+1


source


What do you think it does delete[]

? It calls the destructor of all objects in the array and then frees it. Your pointer is myarr

now pointing to freed memory and is not a valid pointer.

Apparently the memory hasn't been reused yet, so it will still contain the data that was present before it was freed, but this behavior is undefined, which means you can't rely on it. If you do, you'll have all sorts of exciting hard-to-find mistakes one day.

0


source


remove [] call the destructor and then tell the system that the previously allocated memory will no longer be used, but the pointer is still pointing to the starting address.

#include <iostream>

int main(int argc, char *argv[])
{
  int N = 5;
  int *myarr = new int[N];//create an integer array of size 5

  for (int i = 0; i < N; ++i)
    {
      myarr[i] = 45;
      std::cout << myarr[i] << std::endl;
    } 


  delete[] myarr;//kill the memory allocated by new
  std::cout << "Let see if the array was deleted and if we get a segfault \n" ;

  int *dumb = new int[N];

  dumb[3]=0;

  for (int i = 0; i < N; ++i)
    {
      std::cout << myarr[i] << std::endl;
    }


  return 0;
}

      

and the output is:

45
45
45
45
45
Let see if the array was deleted and if we get a segfault 
0
45
45
0
45

      

You are not getting a segmentation fault because the memory is too small and probably has not been reserved by another process. But try this:

#include <iostream>

int main(int argc, char *argv[])
{
  int N = 50000;
  int *myarr = new int[N];//create an integer array of size 5

  for (int i = 0; i < N; ++i)
    {
      myarr[i] = 45;
      std::cout << myarr[i] << std::endl;
    }


  delete[] myarr;//kill the memory allocated by new
  std::cout << "Let see if the array was deleted and if we get a segfault \n" ;
  std::cin >> N;
  int *dumb = new int[N];

  dumb[3]=0;

  for (int i = 0; i < N; ++i)
    {
      std::cout << myarr[i] << std::endl;
    }


  return 0;
}

      

and enter some number, for example. 9000

0


source


Everything already written here is correct, I just want to shed some light on why , what you did is undefined behavior.

  • Regarding the memory allocation for the process, the operating system is not a retailer, you cannot get let say 10 bytes, you can only ask for memory in pages (usually 1 page = 4KiB).
  • But processes run in small chunks, so each process has its own "allocator" - this is an implementation of the new and delete operator . These two beasts sit between your program and the OS. They request memory in pages (for example give me 3 memory pages) and manage those pages for your program (process).
  • If you want to allocate let say 10 bytes, the new statement will allocate (at least) one page (if needed) and give you a pointer pointing to the memory on that page, it will also remember that from that address (which it gave you ) 10 bytes are used.
  • If you don't need those 10 bytes anymore, you call the delete operator - this beast notes that 10 bytes (on the page mentioned above) are no longer used. If the whole page is no longer used , it can(but not required) be freed (returned back to the system). When this happens, if you try to access the freed memory - it will give you a segmentation fault (the page no longer belongs to your process), but if the page has not been returned to the system, it is still available to you (but you don't know for sure )
  • Even if the memory is still available, you shouldn't be accessing it because:
    • the content can be reused for other distributions, which means it can change
    • content can (and often is) used internally by new and deleted structures . If you write to remote memory, it can corrupt these structures, which often leads to segfaults in completely unexpected places (for example, when you delete [] in another completely unrelated place in your code).

Please keep in mind that everything I have written above is only a very simplified version, then it is very difficult, but I hope this gives you an idea of ​​how things work "under the hood". Amen.

0


source







All Articles