Содержимое заголовка Malloc - PullRequest
       0

Содержимое заголовка Malloc

6 голосов
/ 10 октября 2011

Таким образом, в большинстве реализаций malloc хранит заголовок перед выделенной памятью, чтобы отслеживать размер выделенной памяти (чтобы он мог освободиться и выполнить перераспределение).Что такое содержимое заголовка?

Я написал наивный код, чтобы найти его, но он не имеет никакого смысла

int * ptr;
ptr = malloc(12*sizeof(int));
printf("Header = %d\n",*(ptr-1));

Возвращает

Header = 57

Что такоездесь происходит?

Ответы [ 6 ]

15 голосов
/ 11 октября 2011

Полагаю, вы хотите узнать и посмотреть, как распределяется память.Я бы проигнорировал ответы «Неопределенное поведение».Они правы (конечно), когда вы говорите о переносимости и тому подобном, но это не ваш вопрос.Я думаю, что это действительно хорошая идея, чтобы попытаться выяснить, как выполняется распределение.

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

Если вы запускаете linux, вы можете посмотреть на реализацию malloc для glibc или uclibc.Вот ссылка на реализацию uclibc: http://git.uclibc.org/uClibc/tree/libc/stdlib/malloc/malloc.c Код имеет много комментариев, но может быть подавляющим.

По вашему вопросу посмотрите на http://git.uclibc.org/uClibc/tree/libc/stdlib/malloc/malloc.h в строке 104.та часть, о которой ты говоришь.Вы видите, что макет зависит от MALLOC_HEADER_SIZE, который может быть различным для разных систем.Прочитав код, вы можете узнать, какие типы использовать и на каком смещении хранится размер памяти (в данной конкретной реализации)

Конечно, выше приведен только пример реализации из uclibc для начала работы..

6 голосов
/ 20 апреля 2016

Никто так и не ответил, откуда взялась цифра "57", так что вот мое понимание этого.

Заголовок, который устанавливается при использовании malloc или calloc, по крайней мере, на тех архитектурах, которые я использовал, представляет собой общий размер фрагмента памяти в куче времени выполнения плюс несколько «логических флагов».

Вы запросили 12 int, причем каждый int (предположительно) составляет 4 байта. 12x4 = 48. Еще 4 байта, для самого блока заголовка (число 57), добавляются к этому счету, оставляя нас в 52.
Так почему вы получаете 57?

Хорошо, Malloc и Calloc запрашивают память только в 8-битных блоках, чтобы избежать ошибок шины. Следующее более высокое кратное 8 - 56.

Теперь напомним, что любое число, которое делится на 8, имеет двоичное представление, которое всегда заканчивается тремя нулями. Будучи языком сохранения памяти, которым является C, компиляторы используют этот факт и используют последние три 0 в качестве логических флагов.

В этом конкретном случае устанавливается последний логический флаг, добавляя от 1 до 56, что приводит к числу 57 при чтении как int.

4 голосов
/ 10 октября 2011

Ничего из этого не имеет значения (это подробности реализации , непрозрачные для пользователя), и то, что вы делаете, - это неопределенное поведение.

Это все, что касается стандарта.

Теперь, если вы хотите быть непослушным и ковыряться в памяти, имейте в виду, что арифметика указателей работает в единицах размера шрифта (например, 4 для int). Таким образом, вы должны всегда приводить свои указатели к char* (или к неподписанной версии) для таких махинаций:

struct Foo * f = malloc(sizeof(Foo) * 7);
const unsigned char * const i_know_what_im_doing = f;

printf("%02X\n", *(i_know_what_im_doing - 1));
1 голос
/ 10 октября 2011

Это неопределенное поведение. Но, если честно, если вы хотите покопаться во внутренностях malloc, первое, что вам нужно сделать, это определить, что делает ваш malloc.

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

1 голос
/ 10 октября 2011

Вы вызываете Неопределенное поведение .
Попытка чтения за пределами выделенной памяти - это UB.

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

0 голосов
/ 10 октября 2011

С вашим кодом вы читали int раньше, и ничто не говорит вам, что заголовок такой длинный.Более того, это зависит от реализации, поэтому вы никогда не можете на это положиться!

Более того, попытка получить доступ к памяти, которую вы сами не выделили, является неопределенным поведением !!

Я незнаю, почему вы хотите получить к нему доступ, но с этим лучше ничего не делать!

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

Таким образом, ваш заголовок должен содержать хотя бы этот размер.

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

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