What information does new[] save?

2

I have read here How does delete[] "know" the size of the operand array? that before the allocated memory it is saved how much memory it was allocated. I allocated an array of integers, set each element to value 15 and inspected the heap. First I allocated an array with 2 elements:

x/8xw 134524932
0x804b004:    0x00000011    0x0000000f    0x0000000f    0x00000000
0x804b014:    0x00020ff1    0x00000000    0x00000000    0x00000000

and another with 4 elements:

x/8xw 134524932
0x804b004:    0x00000019    0x0000000f    0x0000000f    0x0000000f
0x804b014:    0x0000000f    0x00000000    0x00020fe9    0x00000000

There are several things I do not understand:
1) How the values 0x00000011 and 0x00000019 define the size of the allocation?
2) Is there space for an extra array element allocated?
3) Are the values 0x00020ff1 and 0x00020fe9 at the of the allocated memory related to the allocation?

I am using gcc on a 32bit Ubuntu.

c++
gdb
asked on Stack Overflow Dec 20, 2014 by robert • edited May 23, 2017 by Community

1 Answer

2

The number of elements is typically not stored for primitives, because there is no need to call destructors. Here's an example compiled on 64-bit Linux with g++. Note that most new implementations are layered on malloc(). Typically, malloc() also stores some metadata. You'd typically see that before the metadata stored by C++.

One might ask why C++ needs to store the number of elements if malloc() is also storing size information. The rationale is that coupling your C++ compiler/ABI to the underlying memory allocation implementation is a bad idea from an engineering standpoint.

Of course, this is all platform dependent, and getting at this information invokes undefined behavior. On a different platform, it could cause nasal demons or other demonic behavior, so be sure to have an exorcist with you.

#include <cstddef>
#include <iostream>
#include <cstdlib>

struct A {
    A() : data(count++) {}
    ~A() {}
    const std::size_t data;
    static std::size_t count;
};

std::size_t A::count = 1000;

int
main() {

    {
        A *aa = new A[1234];
        std::cout << "The size_t immediatly before an array of A objects: "
                  << *((std::size_t *) aa - 1) << std::endl;
        delete [] aa;
    }

    // Note that for fundamental types, there is no need to store the size, so it doesn't.
    {
        std::size_t *sa = new std::size_t[5678];
        std::cout << "The size_t before an array of std::size_t objects: "
                  << *(sa - 1) << std::endl;
        delete [] sa;
    }
}
answered on Stack Overflow Dec 20, 2014 by kec

User contributions licensed under CC BY-SA 3.0