-1

I have some problems with void delete[] in C++ Here is my code:

#include<iostream>

int main(){
    int *p = new int[1000];
    for (int i = 1; i <= 1000; ++i)
        p[i] = i;
    delete [] p;
    for (int i = 0; i <= 1000; ++i)
        std::cout << std::endl << p[i];
}

Theoretically, when I call delete [] p, pointer p must be deleted. However, I can still print it to the screen after calling delete [] p. Can anybody explain why?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
pexea12
  • 1,069
  • 2
  • 18
  • 36
  • Os is not forced to deallocate immidiately I think. Maybe after you allocate several gigabytes more after this. Maybe just because you are still in main() . Try allocating with a function and return the pointer and check in main. – huseyin tugrul buyukisik Apr 04 '15 at 08:23
  • 1
    It's undefined behaviour, so anything is allowed to happen, including appearing to work. – Alan Stokes Apr 04 '15 at 08:26
  • Well, can you explain more in detail? I still don't get the point. – pexea12 Apr 04 '15 at 08:26
  • 3
    You're calling undefined behavior to use a pointer after deletion. @huseyintugrulbuyukisik Nonsense. – πάντα ῥεῖ Apr 04 '15 at 08:27
  • 1
    @PeaNguyen Indices starts at 0, not 1, so your first `for` loop is accessing memory out of bounds. So regardless of your question, your code exhibits undefined behavior even before you get to the `delete[]`. – PaulMcKenzie Apr 04 '15 at 08:39
  • `However, I can still print it to the screen after calling delete [] p. Can anybody explain why?` I had my drivers license suspended. How come I can still get in a car and drive it? – PaulMcKenzie Apr 04 '15 at 08:41
  • Deleting allocated memory only makes it illegal to use it. Nothing prevents you from breaking the law. – Galik Apr 04 '15 at 08:43

3 Answers3

6

This is Undefined Behaviour. When you do something against the rules of the language, your program can do anything at all.

C++ (and other languages, notably C) have Undefined Behaviour because it allows compilers to come up with the most efficient implementations on a particular hardware+os combination. Why should the compiler pay the cost of checking this memory every time to give consistent behaviour in this case, when it is useless to be accessing the memory at this point anyway?

Sometimes it might appear to work, sometimes it might crash, sometimes it might set your socks on fire. Not very likely, but completely legal by the rules of the language.

In this particular case, using that memory after it is deleted is not allowed by the language. It just so happens that the system hasn't yet done anything to blank out that memory, or make it inaccessible to your program. That doesn't mean this behaviour is in any way guaranteed, however. The other likely result is a segmentation fault, if the system does make that memory inaccessible. But again, no guarantees.

You can read about other Undefined Behaviour in C++ here.

You should also consider getting a good C++ book, that will teach you to avoid these sorts of mistakes.

Community
  • 1
  • 1
BoBTFish
  • 19,167
  • 3
  • 49
  • 76
1

Your statement delete [] p releases the array of objects pointed to by p. It does not change the value of p, nor does it cause p to no longer exist.

The pointer p continues to exist, until the end of the enclosing scope. Any attempt it - such as printing the elements of the array as in your code - yields undefined behaviour.

If you want the pointer itself to cease to exist, introduce another scope. For example;

#include <iostream>

int main()
{
  {    // new block and scope starts here
    int *p = new int[1000];
    for (int i = 0; i < 1000; ++i)
        p[i] = i;
    delete [] p;
   }    // end of block/scope, so p no longer exists from here
    for (int i = 0; i < 1000; ++i)
        std::cout << std::endl << p[i];   // compilation error
}

(Note that I have incidentally fixed a problem with array bounds that you had in your code).

Better yet, use a std::vector<int> and don't bother with using a pointer, operator new[], nor operator delete[] directly at all. Unlike a pointer, the lifetime of a std::vector<int> is bound to lifetime of its contained elements. That means the elements cease to exist when the std::vector<int> does.

Peter
  • 35,646
  • 4
  • 32
  • 74
0

In short: Accessing memory through a deleted pointer is undefined behavior and this is just one possible incarnation of undefined behavior - as would be ordering pizza.
The point is that you cannot reason about what a program that contains undefined behavior should do or should not do - it is just undefined (this applies to the whole program, not only to the part where UB occures).

MikeMB
  • 20,029
  • 9
  • 57
  • 102