简体   繁体   中英

C++ delete[] on new char;

Consider the following code:

int main()
{
    char* str = new char; 
    str[0] = 'a'; 
    delete[] str; //Notice the []
}

It compiles, runs and nothing crashes (VC15 and g++) It does however have 1 memory leak which I can clearly see with valgrind.

If I run the following code however:

#include <iostream>

class Foo{
public:
    Foo(){
        std::cout << "Foo::Foo" << std::endl;
    }
    ~Foo(){
        std::cout << "Foo::~Foo" << std::endl;
    }
};

int main()
{   
      Foo* foo = new Foo;
      delete[] foo;
      return 0;
}

I get an infinite loop of destructor calls when running on Windows, and an invalid pointer error in Linux (after ~20 d'tors calls).

What I can't figure out is why is there a difference between the two? why don't I get an infinite loop with new char or crash?

You shall use delete[] with and only with a pointer which was allocated using new[] ;

The problem

In your first code snippet:

  • With the statement char* str = new char; you get a pointer to a single char. So the type from new matches the char* .
  • But your delete[] expects a pointer to an array of char, so you get undefined behavior (UB) when you delete something that is not an array

The second code snippet has exactly the same problem. UB is undefined and can give strange and unexplainable results.

How to solve it ?

Either use a single element delete for a single element allocation:

  Foo* foo = new Foo;
  delete foo;

Or use an array delete for an array allocation:

  Foo* foo = new Foo[1];
  delete[] foo;

Or better: get rid of any new/delete you're tempted to use and use vectors instead of arrays.

To make this short, calling delete[] for a pointer that was not allocated with new[] and is not null is always undefined

I quote from cppreference.com :

Called by delete[]-expressions to deallocate storage previously allocated for an array of objects. The behavior of the standard library implementation of this function is undefined unless ptr is a null pointer or is a pointer previously obtained from the standard library implementation of operator new or operator new[](size_t, std::nothrow_t).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM