Я пытаюсь выровнять членов класса по конкретным выравниваниям (например, 128) в C ++ 11, чтобы избежать ложного разделения между потоками.Мой подход заключается в использовании alignas
, но я получаю смешанные результаты.В этой простой программе я получаю желаемые результаты:
#include <cstdio>
#include <atomic>
struct Foo {
char foo[128];
void* x1;
uint32_t x2;
uint32_t x3; // here an "entry" is only the
alignas(128) std::atomic<unsigned int> a;
alignas(16) std::atomic<unsigned int> b;
};
int main(int argc, char const *argv[])
{
Foo x, y;
printf("alignof(Foo x) = %zu\n", alignof(x));
printf("alignof(Foo x.a) = %zu\tmod 128 = %d\n", alignof(x.a), reinterpret_cast<uintptr_t>(&(x.a)) % 128);
printf("alignof(Foo x.b) = %zu\tmod 16 = %d\n", alignof(x.b), reinterpret_cast<uintptr_t>(&(x.b)) % 16);
/* code */
return 0;
}
Однако в более крупной программе с очень похожей структурой классов, а также с использованием alignas
до 128 байтов.Когда я распечатываю alignof
полей, я получаю то, что ожидаю и что я указал в атрибуте alignas
.Однако, когда я изменяю адрес соответствующих полей, я не получаю того же значения, что и аргумент alignas
(128) - я получаю 32. Я ожидаю alignas
, чтобы поместить переменную в памятьв начале адреса памяти, который делится равномерно на 128;действительно ли это ожидание?
Обратите внимание, что в приведенной ниже программе я получаю ожидаемые результаты при компиляции с помощью clang 6.0.1.Я не могу опубликовать эту большую программу, потому что она очень большая и не может быть опубликована.Я также не смог придумать тестовую программу, которая бы воспроизводила конкретную проблему, но я продолжаю пробовать.
Вопросы:
- Естьмой подход к выравниванию определенных членов в классе, рекомендованный для C ++ 11?
- Если нет, каков правильный путь?Является ли добавление фиктивных полей, таких как
char _pad[120]
, правильным? - Должен ли я также выравнивать сам общий класс?Прямо сейчас я не делаю этого явно.