У меня есть следующая структура:
#define M 3
#pragma pack(push)
#pragma pack(1)
struct my_btree_node {
struct my_btree_node *pointers[M];
unsigned char *keys[M - 1];
int data[M - 1];
unsigned char number_of_keys;
};
#pragma pack(pop)
Функция sizeof(struct my_btree_node)
возвращает значение 49 байт для этой структуры. Выделение памяти для этой структуры с помощью malloc
возвращает 64-байтовый блок, потому что в 64-битных системах указатели выровнены по 16 байтам, или это действительно будет 49 байтов?
Есть ли способ выровнять память с меньшей степенью двойки, чем 16, и можно ли внутри приложения получить истинный размер выделенной памяти?
Я хочу уменьшить количество байтов заполнения, чтобы сэкономить память. Мои приложения выделяют миллионы этих структур, и я не хочу тратить память.
2 ответа
malloc(3) определен к
Функции
malloc()
иcalloc()
возвращают указатель на выделенный память, которая подходящим образом выровнена для любого встроенного типа. При ошибке, эти функции возвращаютNULL
.NULL
также может возвращаться успешный вызовmalloc()
с нулевым size или успешным вызовcalloc()
с nmemb или size равным нулю.
Таким образом, соответствующая реализация должна возвращать указатель, выровненный по максимально возможному выравниванию машины (с GCC a>, это макрос __BIGGEST_ALIGNMENT__
)
Если вы хотите меньше, реализуйте собственную процедуру распределения. Вы могли бы, например, выделить большой массив char
и сделать свое распределение внутри него. Это было бы болезненно, возможно, медленнее (процессоры не любят невыровненные данные, например, из-за ограничений кеша ЦП), и, вероятно, не стоит (современные компьютеры имеют несколько гигабайт оперативной памяти, поэтому несколько миллионов фрагментов данных размером в сто байтов не имеют большого значения).
Кстати, malloc
практически реализован в стандартной библиотеке C (но по крайней мере в Linux компилятор знает об этом благодаря __attribute__
-s в заголовки GNU glibc; так что некоторые внутренние оптимизации внутри GCC знают и принимают заботиться о вызовах malloc
).
malloc
использует внутреннюю структуру кучи. Это зависит от реализации, но можно ожидать, что память будет выделена целым числом (внутренних) блоков. Поэтому обычно невозможно выделить ровно 49 байт одним вызовом malloc
. Для этого вы можете построить какую-нибудь собственную подсистему поверх malloc
, но я не вижу причин, по которым вам это может понадобиться.
P.S. Чтобы уменьшить расход памяти, вы можете предварительно выделить массив, состоящий, скажем, из 100 структур, когда вам нужна еще одна, и возвращать &a[i] до тех пор, пока все свободные индексы не будут потрачены впустую. Поскольку массивы никогда не дополняются, потери памяти уменьшатся примерно в 100 раз.
Похожие вопросы
Связанные вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.