4

I tried to deallocate same pointer twice and it failed, but if I follow the same steps with not making it NULL the code runs fine.

 #include <iostream>

    struct MyClass {
      MyClass() {std::cout << "Allocated and Constructed" << std::endl ;} 
    };

    int main () {
      // allocates and constructs five objects:
      MyClass * p1 = new MyClass[5];

      delete[] p1;
      delete[] p1; // The code will succeed if I comment this line of code
      p1=NULL;
      delete[] p1;
      delete[] p1;

      return 0;
    }

I see a good answer to the question What happens when you deallocate a pointer twice or more in C++? but what makes it run if I make it NULL, shouldn't be the same behaviour to follow for both the cases?

Community
  • 1
  • 1
Shrey
  • 1,242
  • 1
  • 13
  • 27

3 Answers3

6

You need to deallocate only what you allocate. You allocate five instances of MyClass with new[]. So that's what you need to deallocate.

You're not deallocating any pointers. Pointers don't need to be deallocated unless you dynamically allocated them, and your code doesn't dynamically allocate any pointers.

When you make the pointer nullptr (or NULL), it doesn't point to anything. So calling delete on it has no effect. The C++ standard chose to make calling delete (or delete[]) on a null pointer do nothing.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
1

delete[] p1; doesn't ususally change the actual value of p1. (Although the C++ standard states that it can set p1 to nullptr on doing this, no compiler I've worked with actually does this).

So the behaviour on a second call to delete[] p1; is undefined since your program no longer owns that memory.

Some programmers consider it good practice to set p1 = nullptr explicitly after a delete[] since then a subsequent delete is benign. But doing that can hide other memory management issues your program has (why would your program attempt to delete the same block of memory more than once?), so I'd advise against it.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1

From the standard, 5.3.5$2 Delete [expr.delete] (bold by me)

In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of delete may be a null pointer value or a pointer value that resulted from a previous array new-expression.81 If not, the behavior is undefined.

It explains why delete a pointer twice is UB, and delete a null pointer is well defined.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405