Подтвердить что ты не робот

Почему Malloc() заботится о выравниваниях границ?

Я слышал, что malloc() выравнивает память по типу, который выделяется. Например, из книги "Понимание и использование указателей C":

Выделенная память будет выровнена в соответствии с типом данных указателя. Например, четырехбайтовое целое будет выделено на границе адреса, равномерно делимой на четыре.

Если я последую, это означает, что int *integer=malloc(sizeof(int)); будет распределяться по границе адреса, равномерно делимой на четыре. Даже без литья (int *) на malloc.

Я работал на чат-сервере; Я читал о аналогичном эффекте с struct s.

И я должен спросить: логично, почему имеет значение, на чем делится граница адреса? Что не так с распределением группы памяти на мелодию n*sizeof(int) с использованием целого числа по адресу 129?

Я знаю, как работает арифметика указателей *(integer+1), но я не могу понять важность границ...

4b9b3361

Ответ 1

Выделенная память будет выровнена в соответствии с данными указателя тип.

Если вы говорите о malloc, это ложь. malloc не заботится о том, что вы делаете с данными, и выделяет выделенную память в соответствии с самым строгим собственным типом реализации.

Из стандарта:

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

и

Логически, почему имеет значение то, что сама граница адреса делится на

Из-за работы базового компьютера доступ к неуравновешенным данным может быть более дорогим (например, x86) или незаконным (например, рукой). Это позволяет аппаратным средствам использовать ярлыки, которые повышают производительность/упрощают реализацию.

Ответ 2

Во многих процессорах данные, которые не выровнены, вызовут "ловушку" или "исключение" (это другая форма исключения, чем те, что поняты компилятору С++. Даже на процессорах, которые не ловутся, когда данные не являются 't выровнен, он, как правило, медленнее (в два раза медленнее, например), когда данные не правильно выровнены. Поэтому в библиотеке компилятора/среды выполнения наилучшим образом интересны, чтобы все было хорошо выровнено.

И, кстати, malloc (обычно) не знает, что вы выделяете. Insteat, malloc выровнят ВСЕ данные, независимо от их размера, к некоторой подходящей границе, которая "достаточно хороша" для общего доступа к данным - обычно 8 или 16 байтов в современных комбинациях ОС/процессоров, 4 байта в старых системах,

Это связано с тем, что malloc не знает, выполняете ли вы char* p = malloc(1000); или double* p = malloc(1000);, поэтому он должен предположить, что вы храните double или что-то другое - это элемент с наибольшим требованием выравнивания.

Ответ 3

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

Ответ 4

Цитата книги неверна; память, возвращаемая malloc, гарантированно будет правильно выровнена для любого типа. Даже если вы пишете char *ch = malloc(37);, он по-прежнему выровнен для int или любого другого типа.

Кажется, вы спрашиваете: "Что такое выравнивание?" Если это так, есть несколько вопросов о SO об этом уже, например. здесь, или хорошее объяснение от IBM здесь.

Ответ 5

Это зависит от оборудования. Даже если int - 32 бита, malloc(sizeof(int)) может вернуть адрес, делящийся на 1, 2 или 4. Различные процессоры обрабатывают неравномерный доступ по-разному.

Процессоры больше не читают напрямую из ОЗУ, что слишком медленно (требуется сотни циклов). Поэтому, когда они захватывают ОЗУ, они захватывают его в больших кусках, как 64 байта за раз. Если ваш адрес не выровнен, целое число в 4 байта может охватывать две 64-байтовые строки кэша, поэтому ваш процессор должен выполнить две нагрузки и исправить результат. Или, может быть, инженеры решили, что создание аппаратного обеспечения для устранения неуравновешенных нагрузок не требуется, поэтому процессор сигнализирует об исключении: либо ваша программа выйдет из строя, либо операционная система поймает исключение и исправит операцию (сотни потраченных впустую циклов).

Выравнивание адресов означает, что ваша программа отлично работает с оборудованием.

Ответ 6

Потому что это быстрее; Большинство процессоров любят данные, которые выровнены. Даже, некоторые процессоры НЕ МОГУТ получить доступ к данным, которые не выровнены! (Если вы попытаетесь получить доступ к этим данным, процессор может возникнуть сбой)