Что такое выравнивание выделения памяти? - PullRequest
14 голосов
/ 22 октября 2010

Я также хочу знать, делает ли это glibc malloc ().

Ответы [ 4 ]

59 голосов
/ 22 октября 2010

Предположим, у вас есть структура.

struct S {
    short a;
    int b;
    char c, d;
};

Без выравнивания он будет размещен в памяти следующим образом (при условии 32-битной архитектуры):

 0 1 2 3 4 5 6 7
|a|a|b|b|b|b|c|d|  bytes
|       |       |  words

Проблема в том, что на некоторых архитектурах ЦП инструкция по загрузке 4-байтового целого числа из памяти работает только на границах слов. Таким образом, ваша программа должна получать каждую половину b с отдельными инструкциями.

Но если память выложена как:

 0 1 2 3 4 5 6 7 8 9 A B
|a|a| | |b|b|b|b|c|d| | |
|       |       |       |

Тогда доступ к b становится простым. (Недостатком является то, что из-за байтов заполнения требуется больше памяти.)

Различные типы данных имеют разные требования к выравниванию. Обычно char выравнивается по 1 байту, short - по 2 байта, а 4-байтовые типы (int, float и указатели в 32-разрядных системах) - 4 байта выровнены.

malloc требуется стандартом C для возврата указателя, правильно выровненного для любого типа данных.

glibc malloc на x86-64 возвращает 16-байтовые совмещенные указатели.

7 голосов
/ 22 октября 2010

Выравнивание Требования указывают, какие смещения адресов могут быть назначены для каких типов.Это полностью зависит от реализации, но обычно основано на размере слова.Например, некоторые 32-разрядные архитектуры требуют, чтобы все int переменные начинались с кратного четырех.На некоторых архитектурах требования выравнивания являются абсолютными.На других (например, x86) их игнорирование сопровождается только ухудшением производительности.

malloc требуется для возврата адреса, подходящего для любого требования выравнивания.Другими словами, возвращаемый адрес может быть назначен указателю любого типа.От C99 §7.20.3 (Функции управления памятью):

Указатель, возвращаемый в случае успешного выделения, соответствующим образом выравнивается, так что он может быть назначен указателю на любой тип объекта и затем использован для доступатакой объект или массив таких объектов в выделенном пространстве (пока пространство не будет явно освобождено).

1 голос
/ 26 декабря 2012

Документация malloc() гласит:

[...] the allocated memory that is suitably aligned for any kind of variable.

Что верно для большинства всего, что вы делаете в C / C ++.Однако, как отмечают другие, существует много особых случаев, которые требуют особого выравнивания.Например, процессоры Intel поддерживают 256-битный тип: __m256, который, безусловно, не учитывается malloc().

Аналогично, если вы хотите выделить буфер памяти для данных, которые должны бытьпостраничная (аналогично адресам, возвращаемым mmap() и т. д.), тогда вам потребуется, возможно, очень большое выравнивание, которое потратило бы много памяти, если бы malloc() возвращал буферы, всегда выровненные по таким границам.Linux или другие системы Unix, я предлагаю вам использовать функцию posix_memalign():

int posix_memalign(void **memptr, size_t alignment, size_t size);

Это самая последняя функция, которую вы хотите использовать для таких нужд.

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

Если у вас есть особые потребности выравнивания памяти (для конкретного оборудования или библиотек), вы можете проверить непереносимые распределители памяти, такие как _aligned_malloc() и memalign(). Их можно легко абстрагировать за «портативный» интерфейс, но, к сожалению, они нестандартны.

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