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.
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;
}
}
User contributions licensed under CC BY-SA 3.0