Reputation: 303147
I want to overalign my type on a cache boundary, so I used alignas
:
struct alignas(64) W { };
This compiles fine. But then, to my surprise, when I try to allocate a bunch of W
s, they're not 64-byte aligned but actually 16-byte aligned:
#include <iostream>
#include <iomanip>
#include <unordered_map>
struct alignas(64) W { };
int main() {
std::unordered_map<int, int> offset;
for (int i = 0; i < 1000; ++i) {
auto w = new W;
offset[(uintptr_t)w % 64]++;
}
for (const auto& p : offset) {
std::cout << p.first << ' ' << p.second << '\n';
}
}
Yields:
0 250
16 250
32 250
48 250
on several compiles (gcc 4.8.2, gcc 5.2.0, clang 3.7.1). What's up? I told it to align, why isn't it aligning?
Upvotes: 7
Views: 2202
Reputation: 6792
The other answer is correct in the sense that it explains the existing limitation, but I'd like to point out that things are about to get better.
As indicated by T.C. in the comments, this was a long-standing deficiency in the language. It looks like the WG effort to fix this has led to a resolution in C++17 (which has just attained feature-complete status). Thus, when compiling to that Standard, overalignment will finally be respected by dynamic allocation, by using the new std::align_val_t
overloads of new
. Thus solving Barry's problem!
Given the amount of new scaffolding required, I presume this won't be backported to earlier versions of the Standard, so the old caveat about their dynamic allocation only sufficing for types having fundamental alignment will presumably remain true.
Upvotes: 2
Reputation: 472
This is answered nicely here: https://stackoverflow.com/a/16510895
Basically: new
(at least in its normal usage) only guarantees a constant maximum alignment (alignof(std::max_align_t)
) for every call to new
.
Upvotes: 3