Saturday, June 12, 2010

new/delete vs new[]/delete[]

The "new" keyword
  • "new" will first created the memory for 1 object and then execute the constructors chain starting from the Derived class recursing to the very Base class and then executing the constructor bodies back up to the Derived.
  • New will throw the std::bad_alloc exception if there isnt enough memory. The exception can be suppressed with "new(nothrow) <object>"
  • Once allocated the size of memory can not be changed as malloc can be with realloc
  • Once allocated the memory can be reinited with "new(<pointer>) <class>". This should only be done in very special cases such as a buffer pool, custom memory management system or something like the vector class. DONT MESS WITH THIS UNLESS YOU HAVE A CLUE.

The "delete" keyword
  • The delete will first call all destructors and then deallocate memory for 1 object.
  • It is safe to pass NULL into delete as it will return directly and perform nothing.
  • Throwing exceptions from inside a delete is technical possible and will result in the abortion of the destructor sequence and failure to deallocate the memory. It is considered bad form because most destructor code doesn't expect to re-called if a failure occurred.
  • delete will not be implicitly called at the end of a program, but the memory will be reclaimed by the system.
  • calling delete on a "new[]" allocated block of data will execute the destructor of the first object only and fail to correctly deallocate the memory. This is deliberating done to support the rebasing new constructor described above. DONT MESS WITH THIS UNLESS YOU HAVE A CLUE.

The "new[]" keyword
  • "new[]" logically the same as "new" but will create and array of memory, and for each will call the constructors like "new" does
  • Items in a "new[]" allocated array can be reinited with the "new" keyword. DONT DO THIS UNLESS YOU REALLY HAVE A CLUE!
  • memory allcated with "new[]" must be deleted with "delete[]", if "delete is used the first items destructor will be called and the memory release will fail. This is to support the reiniting constructor above. DONT MESS WITH THIS UNLESS YOU HAVE A CLUE.

The "delete[]" keyword
  • "delete[]" operates logically the same as the "delete" but removes an array of memory
  • "delete[]" will crash out if handed memory that was allocated by "new"

#include <iostream>
using namespace std;

class Counting
{
public:
  static int total_count;
  int count;
  
  Counting() 
  { 
    count = total_count++; 
    cout << "Counting" << count << " created" << endl;
  }

  ~Counting() 
  { 
    cout << "Counting" << count << " destroyed" << endl;
  } 
};

int Counting::total_count = 0;

class ThrowingDestructor
{
public:
  int count;
  ThrowingDestructor() { count = 2; }
  ~ThrowingDestructor() { count--; if(count > 0) throw "STOP NOW!"; }
};

int main()
{
  ThrowingDestructor* thrower = NULL;

  //this is technically ok but bad form!
  thrower = new ThrowingDestructor(); 
  try 
    { delete thrower; }
  catch (...)
    { cout << "catch1!" << endl; }
  try 
    { delete thrower; }
  catch (...)
    { cout << "catch2!" << endl; }

  Counting* count  = NULL;

  delete count; //OK delete doesnt react to NULLs

  count = new Counting(); 
  delete count;
  //count = new(count) Counting(); //BAD reexecute the constructor on count which is dealloc'ed, will crash

  count = new Counting(); 
  count = new(count) Counting(); //OK reexecute the constructor on count
  delete count;

  count = new Counting[10];
  new(&count[2]) Counting(); //OK will reinit the memory for the item at index 2
  delete[] count;  

  count = new Counting[10];
  delete count;    //BAD will call destrutor of the first element only, and delete will not remove the memory.
  //count = new(count) Counting(); //will not CRASH proving that the memory is still allocated
  delete[] count;  //BAD will now double free the memory and call the first elements destructor again!!!

  count = new Counting();
  //delete[] count;  //BAD will attempt to free space that has not been allocated as an array and crash 
}

No comments:

Post a Comment