Why is the new one allocating 1040 extra bytes the first time?
I was creating this simple test program to demonstrate how alignment works when allocating memory using standard new ...
#include <iostream>
#include <iomanip>
#include <cstdint>
//
// Print a reserved block: its asked size, its start address
// and the size of the previous reserved block
//
void print(uint16_t num, uint16_t size_asked, uint8_t* p) {
static uint8_t* last = nullptr;
std::cout << "BLOCK " << num << ": ";
std::cout << std::setfill('0') << std::setw(2) << size_asked << "b, ";
std::cout << std::hex << (void*)p;
if (last != nullptr) {
std::cout << ", " << std::dec << (uint32_t)(p - last) << "b";
}
std::cout << "\n";
last = p;
}
int main(void) {
// Sizes of the blocks to be reserved and pointers
uint16_t s[8] = { 8, 8, 16, 16, 4, 4, 6, 6 };
uint8_t* p[8];
// Reserve some consecutive memory blocks and print
// pointers (start) and their real sizes
// std::cout << " size start prev.size\n";
// std::cout << "-----------------------------------\n";
for(uint16_t i = 0; i < 8; ++i) {
p[i] = new uint8_t[s[i]];
print(i, s[i], p[i]);
}
return 0;
}
But when I executed the program, I found this strange behavior:
[memtest]$ g++ -O2 mem.cpp -o mem
[memtest]$ ./mem
BLOCK 0: 08b, 0xa0ec20
BLOCK 1: 08b, 0xa0f050, 1072b
BLOCK 2: 16b, 0xa0f070, 32b
BLOCK 3: 16b, 0xa0f090, 32b
BLOCK 4: 04b, 0xa0f0b0, 32b
BLOCK 5: 04b, 0xa0f0d0, 32b
BLOCK 6: 06b, 0xa0f0f0, 32b
BLOCK 7: 06b, 0xa0f110, 32b
As you can see, the second block allocated with the new one is not in the next 32-bit memory address, but far away (1040 bytes). If it's not that strange, uncommenting lines 2 of std :: cout that print out the table header, you get this result:
[memtest]$ g++ -O2 mem.cpp -o mem
[memtest]$ ./mem
size start prev.size
-----------------------------------
BLOCK 0: 08b, 0x1f47030
BLOCK 1: 08b, 0x1f47050, 32b
BLOCK 2: 16b, 0x1f47070, 32b
BLOCK 3: 16b, 0x1f47090, 32b
BLOCK 4: 04b, 0x1f470b0, 32b
BLOCK 5: 04b, 0x1f470d0, 32b
BLOCK 6: 06b, 0x1f470f0, 32b
BLOCK 7: 06b, 0x1f47110, 32b
This is the normal expected result. What makes the new one behave in such a weird way on first launch? I am using g ++ (GCC) 7.1.1 20170516. You can compile without optimization and the result is the same.
source to share
You will be surprised to learn that your program does much more than just allocate multiple memory allocations.
std::cout << "BLOCK " << num << ": ";
Your program also generates formatted output std::cout
using the inline std::streambuf
.
It looks like the first output is not std::cout
allocating a 1024 byte buffer for internal std::streambuf
. This happens after your first selection new
and before your second. The buffer only needs to be allocated once, the first time it is used.
While it goes without saying that the internal memory allocation details are highly implemented, this seems to be the most likely explanation in your case.
source to share
new
does not guarantee that blocks of memory are sequential.
Also, I recommend that you read the Fragmentation , which is most likely happening and the system is trying to fill the holes.
source to share