2015-05-05 5 views
1

Как malloc() хранит метаданные?Динамическое распределение памяти

void* p; 
void* q; 
p = malloc(sizeof(char)); 
q = malloc(sizeof(int)); 

Я знаю, что возвращаемое значение р [0] указывает на начало выделенного блока памяти,

, чем если бы я итерацию и печать

р [-1], р [- 2] .... q [-1], q [-2] ....

или p [1], p [2], p [3], p [4] .... или q [1], q [2], q [3], q [4] ....

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

Пожалуйста, дайте мне некоторое подробное объяснение этой ценности?

+0

Существует много реализаций malloc(), и они не все хранят метаданные одинаково. –

+0

Пример широко используемой реализации GNU находится здесь: https://sourceware.org/git/?p=glibc.git;a=tree;f=malloc –

+1

Это может быть опечатка, но ваши объявления 'p' и 'q' недействительны. Вам лучше использовать следующие 'void * p, * q;' – ForceBru

ответ

0

Дэвид Hoelzer имеет отличный ответ, но я хотел последовать его прикосновение больше:

«Meta Data» для таНоса приводимых реализаций 100%. Вот краткий обзор некоторых реализаций, которые я написал или использовал:

  • Метаданные хранят «следующие» указатели блоков.
  • В нем хранятся значения канарейки, чтобы убедиться, что вы не записали их в конце блока.
  • Метаданных нет, потому что все блоки имеют одинаковый размер, и они помещаются в стек, чтобы позволить O (1) доступ - Абонент-распределитель. В этом случае вы попали бы в память из соседнего блока.
  • Данные хранят следующий блок ptr, prev block ptr, идентификатор выравнивания, размер блока и идентификатор, который сообщает отладчику памяти точно, где произошло распределение. Очень полезно для отслеживания утечки.
  • Бьет данные предыдущего блока, поскольку данные хранятся в хвосте блока вместо головы ...

Или смешивать и сочетать все выше. В любом случае, чтение mem[-1] - плохая идея, а в некоторых случаях (мышление встроенных систем) действительно может вызвать ошибку сегмента только для чтения, если упомянутое считывание выходит за пределы текущей страницы памяти и в запретную область памяти.


Дополнение за OP

4-схема я описал это тот, который имеет довольно много информации для каждого блока - 16 байта информации не является редкостью в том, что размер не скинет общего выравнивания схем. Он будет содержать 4-байтовый указатель на следующий выделенный блок, 4-байтовый указатель на предыдущий, идентификатор для выравнивания - один байт может обрабатывать это непосредственно для общих размеров выравнивания по 0-256 байт, но этот байт также может представляют собой 256 возможных значений переименования выравнивания, 3 байта значений пэда или канарейки и 4-байтовый уникальный идентификатор, чтобы определить, где в коде был выполнен вызов, хотя он может быть уменьшен. Это может быть значение поиска для таблицы отладки, которая содержит __file__, __line__ и любую другую информацию, которую вы хотите сохранить с помощью alloction.

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

+0

Спасибо за ответ, я использую реализацию 4-го типа, вы можете объяснить мне что-то более, возможно, с некоторым примером ... – Dado

+0

Что относительно идентификатора выравнивания? Используется ли для определения того, является ли блок целыми числами, char и т. Д. .? – Dado

+0

Идентификатор выравнивания может быть чем угодно, но обычно это значение 2-го числа, которое указывает, какое выравнивание этот блок использует 1,2,4,8,16 ... Он также может быть отрицательным числом, чтобы указать, что он выделен от задней части кучи вместо передней, общей для борьбы с проблемами фрагментации памяти. –

0

Неверный доступ к p[-1] и т. Д. В вашем примере. Результаты будут неопределенными и могут привести к повреждению памяти или сбою сегментации. В общем, вы вообще не получаете никакого контроля над malloc() или информацией о том, что он делает.

При этом некоторые библиотеки замены malloc() будут давать вам более тонкий контроль или информацию - вы связываете их с вашим двоичным «сверху» системы malloc().

+0

Отсутствие повреждения памяти или ошибки сегментации вообще, если я напечатаю это значение, я получаю все те же значения – Dado

+1

@ Дадо: только потому, что он работает в некоторых примерах игрушек не означает, что он будет продолжать работать. Вы в корне инициируете неопределенное поведение, которое может быть реальной временной бомбой в программе. – nneonneo

+0

@Dado - 'valgrind' не согласен с вами. Как и несколько популярных реализаций malloc(), которые будут/немедленно/segfault. – BadZen

0

В стандарте C не указывается, как malloc хранит свои метаданные (или даже если у него будут доступные метаданные); поэтому формат и местоположение метаданных зависит от реализации. Поэтому переносимый код никогда не пытается получить доступ или проанализировать метаданные.

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

3

Как эти метаданные работают и используются, полностью зависит от управления памятью в вашем libc. Вот несколько полезных рекомендаций для начала работы:

  • Malloc - Как правило, классический malloc.
  • DLMalloc - Doug Lee's Malloc.
  • GC Malloc - Malloc с мусором коллекции.
  • TC Malloc - Thread caching malloc.

Каждый из них имеет разные цели, преимущества и возможные недостатки. Например, возможно, вас беспокоят возможные проблемы переполнения кучи и защиты. Это может привести к одному выбору. Возможно, вы ищете лучшее управление фрагментами. Это может привести к выбору малкома Дуга Ли. Вам действительно нужно указать, какую библиотеку вы используете, или исследовать их все, чтобы понять, как метаданные используются для хранения бункеров, объединения свободных регионов и т. Д.

Смежные вопросы