Когда ОС загружает процесс в память, она инициализирует указатель стека на виртуальный адрес, который она решила, где стек должен идти в виртуальном адресном пространстве процесса, и программный код использует этот регистр, чтобы узнать, где находятся переменные стека. У меня вопрос: как malloc () узнает, с какого виртуального адреса начинается куча? Всегда ли куча существует в конце сегмента данных, и если да, то как malloc () узнает, где она находится? Или это даже одна непрерывная область памяти или просто случайным образом перемежающаяся с другими глобальными переменными в разделе данных?
Как malloc () узнает, где начинается куча?
Ответы (3)
malloc реализации зависят от операционной системы; таков процесс, который они используют для получения начала кучи. В UNIX это можно сделать, позвонив sbrk(0) во время инициализации. В других операционных системах процесс другой.
Обратите внимание, что вы можете реализовать malloc, не зная расположения кучи. Вы можете инициализировать список свободных номеров значением NULL и вызывать sbrk или аналогичную функцию с размером выделения каждый раз, когда не обнаруживается свободный элемент подходящего размера.
Речь идет только о реализациях 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 легко читается.
В Windows вы используете Функции кучи для получения памяти кучи процесса. Среда выполнения C будет выделять блоки памяти в куче, используя HeapAlloc, а затем использовать это для выполнения malloc запросов.
malloc()просто спрашивает? - person jxh   schedule 11.09.2014