Wednesday, March 2, 2011

Where array count is stored when new[] is called?


[source code]
 
#include <new> // for size_t
#include <stdio.h>

class A 
{
public:
  A() {}
  virtual ~A() {}
  static void* operator new (size_t size)
  {
    void* res = ::operator new(size);
    printf("new   return %p\n", res);
    return res;
  }
 
  static void operator delete (void *p)
  {
    printf("delete       %p\n", p);
    ::operator delete(p);
  }
 
  static void* operator new[](size_t size)
  {
    void* res = ::operator new(size);
    printf("new[] return %p\n", res);
    return res;
  }
 
  static void operator delete[](void *p)
  {
    printf("delete[]     %p\n", p);
    ::operator delete[](p);
  }
};
 
void foo()
{
  A* a = new A;
  printf("a=           %p\n", a);
  delete a;
}
 
void bar()
{
  A* a = new A[5];
  printf("a=           %p\n", a);
  delete []a;
}
 
int main()
{
  foo();
  printf("\n");
  bar();
}
 
 
[result]
 
new   return 00633B88 // same
a=           00633B88 // same
delete       00633B88 // same

new[] return 00631A90
a=           00631A94 // 4 byte skipped !!!
delete[]     00631A90


When new[] is called, you can figure out that array count value(5) is stored prior to new[] operator return pointer value(4 bytes offset in the above result). Of course(as you guess), when delete[] is called, the count value is used to delete all allocated objects.

2 comments:

gilgil said...

----- pseudo code of new -----

A* a = new A;

res = malloc(sizeof(A));
call constructor of a;
set virtual table of a;
return res

----- pseudo code of new[] -----

A* a = new A[5];

res = malloc(sizeof(A) * 5) + sizeof(size_t);
*(size_t&)res = 5;
for (int i = 0; i < 5; i++)
{
call constructor of a[i];
set virtual table of a[i];
}
return res + sizeof(size_t);

gilgil said...

Array count is stored and used only in case that the class (or its parents class) has destructor code.