Выравнивание массивов символов - PullRequest
5 голосов
/ 24 октября 2010

Как обычно реализуется вектор STL?У него есть сырое хранилище char [], которое он иногда изменяет по определенному коэффициенту, а затем вызывает размещение нового, когда элемент является push-back (очень интересная грамматическая форма, которую я должен отметить - лингвисты должны изучать такие формы глаголов как pressed_back:)
И тогда есть требования выравнивания.Поэтому возникает естественный вопрос, как я могу назвать место размещения новым на символе [] и убедиться, что требования выравнивания выполнены.Поэтому я искал в стандарте C ++ 2003 года слово «выравнивание» и обнаружил следующее:

Пункт 3.9 Пункт 5

Типы объектов имеют требования к выравниванию (3.9.1, 3.9.2).Выравнивание полного типа объекта представляет собой целочисленное значение, определяемое реализацией, представляющее количество байтов;объект размещается по адресу, который соответствует требованиям выравнивания его типа объекта.

Пункт 5.3.4 Пункт 10:

Новый-expression передает количество пространства, запрошенное для функции выделения, в качестве первого аргумента типа std :: size_t.Этот аргумент должен быть не меньше размера создаваемого объекта;он может быть больше размера создаваемого объекта, только если объект является массивом.Для массивов char и unsigned char разница между результатом выражения new и адресом, возвращаемым функцией размещения, должна быть целым кратным наиболее строгого требования выравнивания (3.9) любого типа объекта, размер которого не превышаетразмер создаваемого массива.[Примечание: поскольку предполагается, что функции выделения возвращают указатели на хранилище, которые соответствующим образом выровнены для объектов любого типа, это ограничение накладных расходов на выделение массивов позволяет распространить идиому распределения массивов символов, в которые впоследствии будут помещены объекты других типов.]

Эти два дают вполне удовлетворительный ответ на мой вопрос выше, но ...

Statement1:
Требование выравнивания для объекта типа X, где sizeof (X) == n - это, по крайней мере, требование, чтобы адрес X делился на n или что-то подобное (поместите все зависящие от архитектуры вещи в "или что-то подобное").

Вопрос1: Пожалуйста, подтвердите, уточните или отклоните вышеприведенный оператор 1.

Оператор 2: Если оператор1 верен, то из второй цитаты в стандарте следует, что выделен массив из 5000000 символовпо адресу, кратному 5000000, что совершенно не нужно, если мне просто нужен массив char как таковой, а не как необработанное хранилище для возможного размещения других объектов.

Вопрос2: Итак, действительно ли шансы на успешное распределение 1000 символов на самом деле ниже, чем 500 символов (при условии, что длина составляет 2 байта)?Это практически проблема?

Ответы [ 3 ]

4 голосов
/ 24 октября 2010

Когда вы динамически выделяете память, используя operator new, у вас есть гарантия, что:

Возвращаемый указатель должен быть соответствующим образом выровнен, чтобы его можно было преобразовать в указатель любого полного типа объекта и затем использовать для доступа к объекту или массиву в выделенном хранилище (до тех пор, пока хранилище не будет явно освобождено путем вызова соответствующего функция освобождения) (C ++ 03 3.7.3.1/2).

vector не создает массив char; он использует распределитель. Распределитель по умолчанию использует ::operator new для выделения памяти.

3 голосов
/ 24 октября 2010

Требование выравнивания для объекта типа X, где sizeof (X) == n - это, по крайней мере, требование, чтобы адрес X делился на n или что-то подобное

Нет,Требование выравнивания типа всегда является фактором его размера, но не обязательно должно быть равным его размеру.Обычно он равен наибольшему из требований выравнивания всех членов класса.

Массив из 5M char, по своей собственной информации, должен иметь только требование выравнивания 1, такое же, как выравниваниетребование единственного char.

Таким образом, текст, который вы цитируете о выравнивании памяти, выделенной через глобальный оператор new, (и malloc имеет аналогичное, хотя требование IIRC не идентичное) в действительности означаетчто большое распределение должно соответствовать самым строгим требованиям к выравниванию любого типа в системе.Кроме того, реализации часто исключают из этого большие типы SIMD и требуют, чтобы память для SIMD была специально выделена.Это немного сомнительно, но я думаю, что они оправдывают это тем, что нестандартные типы расширений могут предъявлять произвольные специальные требования.

Так что на практике число, которое вы считаете 5000000, часто равно 4: -)

1 голос
/ 24 октября 2010

Q1: Выравнивание не связано с размером.

Q2: Теоретически да, но вы вряд ли найдете архитектуру с таким типом выравнивания.SSE требует выравнивания 16 байтов (самое большое, что я видел).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...