Как malloc () узнает, где начинается куча?

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


person mclaassen    schedule 11.09.2014    source источник
comment
Его можно жестко запрограммировать.   -  person    schedule 11.09.2014
comment
Я предполагаю, что это будет зависеть от платформы. Вы заинтересованы в получении ответа для конкретной платформы?   -  person R Sahu    schedule 11.09.2014
comment
возможный дубликат Как работают malloc () и free ()?   -  person ControlAltDel    schedule 11.09.2014
comment
@RSahu Допустим, Linux.   -  person mclaassen    schedule 11.09.2014
comment
@ControlAltDel Я понимаю концепцию того, как работает malloc, я просто не понимаю, как он знает, где на самом деле начинается куча.   -  person mclaassen    schedule 11.09.2014
comment
Довольны ли вы тем, что ОС знает эту информацию, а malloc() просто спрашивает?   -  person jxh    schedule 11.09.2014


Ответы (3)


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

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

person Sergey Kalinichenko    schedule 11.09.2014
comment
Ааааааааааааааааааааааааааааааааааааааааааааааа! Это именно то, что я искал. - person mclaassen; 11.09.2014
comment
Другой упомянутый ответ сбивал с толку из-за этой строки. Системный вызов sbrk перемещает границу сегмента данных., И, насколько я понимаю, сегмент данных, где хранятся глобальные данные. Поэтому я предположил, что куча должна находиться в конце сегмента данных, но не понял, как malloc () может узнать, где находится конец. - person mclaassen; 11.09.2014

Речь идет только о реализациях malloc в Linux.

Многие malloc реализации в Linux или Posix используют mmap (2) syscall, чтобы получить довольно большой диапазон памяти. затем они могут использовать munmap (2) для его выпуска.

(Похоже, sbrk (2) может не больше не использовать; в частности, он не поддерживает ASLR и может не поддерживать многопоточность)

Оба этих системных вызова могут быть довольно обширными, поэтому некоторые реализации запрашивают память (с использованием mmap) довольно большими фрагментами (например, фрагментом в один или несколько мегабайт). Затем они управляют свободным пространством как, например, связанные списки блоков и т. д. Они будут обрабатывать маленькие и большие маллоки по-разному.

Системный вызов mmap обычно не начинает указывать диапазон памяти для некоторых фиксированных частей (в частности, из-за ASLR.

Попробуйте в своей системе запустить простую программу, выводящую результат одного malloc (например, 128 int-s). Вы, вероятно, будете наблюдать разные адреса от одного запуска к другому (из-за ASLR). И strace (1) - это очень поучительно. Попробуйте также cat /proc/self/maps (или распечатайте строки /proc/self/maps внутри вашей программы). См. proc (5)

Таким образом, нет необходимости «запускать» кучу по какому-либо адресу, а во многих системах это не имеет даже никакого смысла. Ядро выдает сегменты виртуальных адресов случайным страницам.

Кстати, как GNU libc, так и musl libc - это бесплатное программное обеспечение. Вам следует заглянуть внутрь исходного кода их malloc реализации. Я считаю, что исходный код musl libc легко читается.

person Basile Starynkevitch    schedule 11.09.2014

В Windows вы используете Функции кучи для получения памяти кучи процесса. Среда выполнения C будет выделять блоки памяти в куче, используя HeapAlloc, а затем использовать это для выполнения malloc запросов.

person MicroVirus    schedule 11.09.2014