3

Consider the following code which contains a class with overloads for new and new[]:

#include <iostream>


class my_class  {
public:
    my_class() {};
    my_class(const my_class& rhs) {};
    ~my_class() {};

//the constructor also as applicable.
    void * operator new(size_t sz); 
    void * operator new[](size_t sz);
    void operator delete(void * ptr);
    void operator delete[](void * ptr);
private:    
};

void * my_class::operator new(size_t sz)
{
    std::cout << "at operator new, sz is: " << sz << std::endl;
}

void * my_class::operator new[](size_t sz)
{
    std::cout << "at operator new[], sz is: " << sz << std::endl;
}

void my_class::operator delete(void * ptr)
{
    std::cout << "at operator delete, ptr is: " << ptr << std::endl;
}

void my_class::operator delete[](void * ptr)
{
    std::cout << "at operator delete[], ptr is: " << ptr << std::endl;
}

int main(int argc, char ** argv)
{
    my_class * ptr = new my_class;
    my_class * arr_ptr = new my_class[1];
    return 0;
}

Running this in the terminal (Cygwin) I see:

at operator new, sz is: 1
at operator new[], sz is: 9

Why is sz == 9 when operator new[] is called ? Who sets it? What does it depend on (eg. page size?)?

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
k_l
  • 189
  • 1
  • 3
  • Fist of all, your `new` should actually return something (and not `NULL`). Until then this has UB. – Baum mit Augen May 17 '15 at 13:25
  • agreed, this is not meant to be a proper implementation, just an investigation on how size_t sz is computed – k_l May 17 '15 at 13:27

2 Answers2

2

A new-expression, like new my_class does more than call operator new; operator new only allocates memory, and its parameter is the size of the memory it is supposed to allocate.

The parameter sz of operator new is 1 because that's the smallest possible instance; sizeof(my_class) is 1.

The parameter sz of operator new[] is 9 because that is how much memory the new[]-expression (new my_class[1]) requires for allocating an array of 1 instance of size 1.

The "extra" 8 is for keeping track of things like how many elements there are.
The size of the "extra" memory is implementation-dependent.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • Thanks for this, I changed the array size and I can confirm what you say is true. – k_l May 17 '15 at 14:16
1

The runtime "sets" the value when you invoke the operator new. There is an implicit sizeof passed around. It is the same situation as with invoking member functions without implicitly passing around the pointer to the current instance this.

In your case you have a class with no members, so theoretically its size should be zero, however C++ allocates one byte (due to the fact that the objects must at least be addressable). That's why the result of the first allocation is 1 (assuming you fix your operators new/new[] to return something, until then you have UB). The second allocation returns 9 due to how C++ represents dynamic arrays, it puts some header somewhere (implementation defined) so it recognizes it is an array (so when invoking operator delete[], the latter behaves properly) and perhaps due to padding.

Community
  • 1
  • 1
vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • So as I am using Windows, would it be the windows runtime that determine this ? – k_l May 17 '15 at 13:31
  • By runtime I mean the standard library shared libraries that are used when your program runs, in combination with the operating system. I am not absolutely sure how this works internally, probably everything translates to some OS system calls, in which the `sizeof` is passed around. See http://stackoverflow.com/questions/3900549/what-is-runtime for a bit of details about runtime. – vsoftco May 17 '15 at 13:39