схема выделения памяти malloc в C - PullRequest
4 голосов
/ 17 июня 2011

Я экспериментировал с malloc в C, и я заметил, что malloc тратит некоторое пространство после выделения некоторой памяти. Ниже приведен фрагмент кода, который я использовал для тестирования malloc

#include <stdlib.h>
#include <string.h>

int main(){
    char* a;
    char* b;
    a=malloc(2*sizeof(char));
    b=malloc(2*sizeof(char));
    memset(a,9,2);
    memset(b,9,2);
    return 0;
}

В правой средней части следующего изображения (для ясности откройте изображение на новой вкладке) вы можете увидеть содержимое памяти: 0x804b008 - это адрес, указанный в переменной «a», а 0x804b018 - это память, указанная в переменной «b». ». что происходит с памятью между 0x804b00a и 0x804b017? Дело в том, что даже если я попытаюсь выделить 3*sizeof(char) вместо 2*sizeof(char) байтов памяти, расположение памяти будет таким же! Итак, что-то мне не хватает?

gdb interface

Ответы [ 5 ]

8 голосов
/ 17 июня 2011

malloc() разрешено тратить столько места, сколько он хочет - стандарт не указывает ничего о реализации.Единственная гарантия, которую вы имеете, касается выравнивания ( §7.20.3 Функции управления памятью ):

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

Ваша реализация, по-видимому, возвращает вам минимумВыровненные по 8 байтов указатели.

3 голосов
/ 17 июня 2011

Выравнивание памяти! Это хорошо для производительности в x86 и обязательно в некоторых архитектурах, таких как ARM.

Большинство процессоров требуют, чтобы объекты и переменные находились с определенными смещениями в памяти системы. Например, 32-разрядные процессоры требуют, чтобы 4-байтовое целое число находилось по адресу памяти, который делится равномерно на 4. Это требование называется «выравниванием памяти». Таким образом, 4-байтовое int может быть расположено по адресу памяти 0x2000 или 0x2004, но не по адресу 0x2001. В большинстве систем Unix попытка использования выровненных данных приводит к ошибке шины, что приводит к полной остановке программы. На процессорах Intel поддерживается использование выровненных данных, но с существенным снижением производительности. Поэтому большинство компиляторов автоматически выравнивают переменные данных в соответствии с их типом и конкретным используемым процессором. Вот почему размер, который занимают структуры и классы, часто больше, чем сумма их членов '

http://www.devx.com/tips/Tip/13265

2 голосов
/ 17 июня 2011

Куча обрабатывается реализацией, не обязательно, как вы ожидаете. Стандарт явно не гарантирует ничего о порядке или смежности. Есть две основные вещи, которые заставляют использовать больше пространства кучи, чем вы просили.

Во-первых, выделенная память должна быть выровнена так, чтобы она подходила для использования любым объектом. Как правило, компьютеры ожидают, что примитивные объекты данных N байтов будут выделены кратно N, так что, скорее всего, вы не сможете получить malloc(), чтобы вернуть значение, не кратное 8.

Во-вторых, необходимо управлять кучей, так что free() позволяет повторно использовать память. Это означает, что диспетчер кучи должен отслеживать выделенные и нераспределенные блоки и их размеры. Один из способов - поместить некоторую информацию в память непосредственно перед каждым блоком, чтобы менеджер мог знать, какой размер блока нужно освободить, и где находятся блоки, которые можно использовать повторно. Если это то, что делает ваша система, то между выделенными блоками будет использоваться больше памяти, а учитывая ограничения выравнивания в 8 байтов, скорее всего, вы не сможете получить выделения менее 16 байтов.

0 голосов
/ 17 июня 2011

malloc гарантированно вернет вам только тот блок памяти, который по крайней мере такой же большой, как размер, который вы ему даете.Однако процессоры, как правило, более эффективны, когда работают с блоками памяти, которые начинаются с, скажем, 8 байтов в памяти.Посмотрите размер слова для получения дополнительной информации об этом.

0 голосов
/ 17 июня 2011

Большинство современных malloc() реализаций распределяются по степеням два и имеют минимальный размер распределения, чтобы уменьшить фрагментацию, так как размеры странного шара обычно могут быть использованы повторно только тогда, когда достаточно непрерывных распределений free() d, чтобы сделать более крупные блоки.(Это также ускоряет объединение смежных распределений вообще, IIRC.) Также имейте в виду накладные расходы блока;чтобы получить размер блока, вам нужно добавить некоторое количество (8 в GNU malloc(), IIRC) для внутреннего управления.

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