I'm moving some C++17 code to be used in a project that is built with Qt, on Windows, using MinGW 7.3.0, and noticed something weird happening in the 32bit builds:
#include <cstddef>
#include <iostream>
int main() {
std::cout << __STDCPP_DEFAULT_NEW_ALIGNMENT__ << std::endl;
std::cout << __BIGGEST_ALIGNMENT__ << std::endl;
std::cout << sizeof(std::max_align_t) << std::endl;
std::cout << alignof(std::max_align_t) << std::endl;
std::cout << "----------------------------------------" << std::endl;
for (int i = 0; i < 8; ++i) {
const uintptr_t ptr = uintptr_t(new char);
static const uintptr_t first = ptr;
std::cout << (ptr - first) << " " //
<< (ptr % 16) << " " //
<< (ptr % 8) << std::endl;
}
return 0;
}
Outputs:
16
16
24
8
----------------------------------------
0 8 0
48 8 0
64 8 0
80 8 0
96 8 0
112 8 0
128 8 0
144 8 0
The same thing happens if I use bigger types / structs instead of char
, and also if I call ::operator new(size_t)
directly with various sizes, instead of the new operator.
As you can see, STDCPP_DEFAULT_NEW_ALIGNMENT
is 16, but I get pointers that are only 8-aligned.
My understanding was that in C++17 operator new(size_t)
would always return pointers with alignment of at least STDCPP_DEFAULT_NEW_ALIGNMENT
, and the two parameter operator new(size_t, align_val_t)
is only required for alignments exceeding STDCPP_DEFAULT_NEW_ALIGNMENT
. Here, it seems, operator new(size_t)
only respects the lower alignof(std::max_align_t)
.
Is this expected behavior? What am I getting wrong here? This seems to contradict my reading of: https://en.cppreference.com/w/cpp/memory/new/operator_new
malloc
itself. – Sennitstruct alignas(__BIGGEST_ALIGNMENT__) foo {};
and thennew foo;
? – MaurineMEMORY_ALLOCATION_ALIGNMENT
, and for 32bit this is 8. – Deerdre