Почему компилятор жалуется на выравнивание?

Я хотел бы понять больше о выравнивании. Почему компилятор Microsoft (Visual Studio 2012 Express) жалуется на выравнивание для следующего фрагмента кода?

__declspec(align(16)) class Foo
{
public:
virtual ~Foo() {}
virtual void bar() = 0;
};

Это предупреждение, которое компилятор представляет мне:

warning C4324: 'Foo' : structure was padded due to __declspec(align())

Даже не имеет значения, есть ли у класса какие-либо виртуальные методы. Даже для пустого класса компилятор жалуется тем же предупреждающим сообщением. Как выровнять пустой класс? Как компилятор дополняет этот класс?

10

Решение

Предупреждение не обязательно означает, что вы сделали что-то не так, но говорит о том, что вы может быть не предполагал такое поведение. Обратите внимание, что компилятор может предупреждать обо всем, о чем разработчики посчитали нужным предупредить. В принципе вас также могут предупредить о компиляции в пятницу 13-го.

В этом конкретном случае, вероятно, предполагается, что когда вы указываете выравнивание, вы не хотите увеличивать класс. Поэтому, если класс становится больше из-за заданного вами требования к выравниванию, вы не ошиблись.

Конечно, это оставляет вопрос, почему требование выравнивания делает класс больше. Теперь мы вернулись в землю стандартов (хотя __declspec само по себе является расширением Microsoft и не является стандартным). Стандарт C ++ требует, чтобы в массивах объекты следовали друг за другом без пробела между ними. Поэтому, если ваши объекты должны быть выровнены по 16-байтовым границам, размер объекта должен быть кратным 16. Если размер элементов (как явных, так и неявных) не дает необходимого размера, компилятор должен добавить неиспользуемые байты к объекту. Эти байты называются дополнением. Обратите внимание, что этот отступ присутствует даже в объектах, которые не являются членами массивов.

Теперь ваш класс содержит только неявный виртуальный указатель (потому что он содержит виртуальные функции), который, в зависимости от архитектуры, вероятно, имеет размер 4 или 8 байт. Поскольку вы запросили 16-байтовое выравнивание, компилятор должен добавить 12 или 8 байтов заполнения, чтобы получить размер, кратный 16, который он не должен был бы добавлять без этой спецификации ручного выравнивания. И это то, о чем предупреждает компилятор.

16

Другие решения

В x86 Foo требуется 4 байта, поэтому требуется 12-байтовая клавиатура. В x64 Foo требуется 8 байтов, поэтому требуется 8-байтовая панель.

3

Это предупреждение говорит о том, что размер класса (как sizeof) изменился (увеличился) в результате использования __declspec(align()), Это может сломать вещи, таким образом, предупреждение.

Конечно, пустой класс имеет размер и должен быть больше 0, поэтому он равен как минимум 1.

Обычно размер не изменяется с выравниванием, но в вашем случае это происходит, потому что вы указали выравнивание, которое больше, чем размер класса без отступов. И помните, что в C выравнивание типа не может быть меньше его размера, на самом деле размер должен быть кратным выравниванию, поэтому размер увеличивается в соответствии с выравниванием.

Почему размер должен быть кратным выравниванию? Хорошо, представьте массив этого типа: последовательные элементы должны быть разделены точно sizeof(T), но каждый объект должен быть в адресе памяти, кратном выравниванию. Единственное решение этого уравнения состоит в том, что sizeof(T) должен быть (ненулевым) кратным выравнивания.

2

Когда вы увеличиваете выравнивание вашей структуры, используя
__declspec(align()) или же alignas(), это не только заставляет вашу структуру быть более строгой, но может должен подушечка ваша структура в конце, в соответствии с этим правило:

Размер структуры является наименьшим кратным ее выравнивания, большим или равным смещению конца ее последнего элемента.

Другими словами, если вы увеличите выравнивание структуры, скажем, 16, вам лучше убедиться, что размер вашей структуры также кратен 16, или вы рискуете изменить размер структуры из-за заполнения, что может привести к вашей программе сломаться (компилятор не может сказать, насколько вы полагаетесь на размер ваших структур и знаете ли вы об этом правиле, поэтому он выдает предупреждение).

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector