Malloc резервирует больше места, выделяя память?
Я наблюдаю следующее поведение в моей тестовой программе:
Я делаю malloc()
для 1 МБ и затем free()
после sleep(10)
. Я делаю это пять раз. Я наблюдаю потребление памяти в top
во время работы программы.
После free()
-d я ожидаю, что потребление виртуальной памяти программы (VIRT) уменьшится на 1 МБ. Но на самом деле это не так. Он остается стабильным. Чем объясняется такое поведение? malloc()
делает некоторый резерв при выделении памяти?
Ответы
Ответ 1
После free()
-d я ожидаю, что потребление виртуальной памяти программы (VIRT) сократится на 1 МБ.
Ну, это не гарантируется стандартом C. Он только говорит, что, как только вы free()
память, вы больше не должны обращаться к ней.
Будет ли блок памяти фактически возвращен в доступный пул памяти или оставлен в стороне для будущих распределений, решается диспетчером памяти.
Ответ 2
Стандарт C не навязывает реализации malloc
и может free
возвращать память в ОС. Таким образом, различные реализации библиотеки C будут вести себя по-разному. Некоторые из них могут вернуть его напрямую, а некоторые нет. Фактически, одна и та же реализация будет вести себя по-разному в зависимости от размеров и шаблонов распределения.
Такое поведение, конечно, по уважительным причинам:
- Это не всегда возможно. Распределение памяти на уровне ОС обычно выполняется в страницах (4 КБ, 4 МБ или... размеры одновременно). И если небольшая часть страницы все еще используется после освобождения другой части, то страница не может быть возвращена операционной системе, пока эта часть также не будет освобождена.
- Эффективность. Весьма вероятно, что приложение снова запросит память. Так зачем возвращать его обратно в ОС, а вскоре после этого попросить снова. (конечно, возможно, существует ограничение на размер сохраняемой памяти.)
В большинстве случаев вы не несете ответственности за объем free
памяти, если реализация решила сохранить ее (при условии, что это хорошая реализация). Рано или поздно он будет перераспределен или возвращен в ОС. Следовательно, оптимизация использования памяти должна основываться на количестве, которое у вас есть malloc
-ed, а вы не free
-d. В этом случае вам нужно беспокоиться, когда ваши шаблоны/размеры выделения начинают вызывать фрагментацию памяти, что само по себе является очень большой темой.
Однако, если вы находитесь во встроенной системе и объем доступной памяти ограничен, и вам нужно больше контролировать, когда и как память выделяется и освобождается, вам нужно напрямую запросить страницы памяти у ОС и управлять ею вручную.
Редактировать: я не объяснил, почему вы не несете ответственности за память, которую вы свободны. Причина в том, что в современной ОС выделенная память является виртуальной. Это означает, что если вы выделите 512 МБ в 32-разрядной системе или 10 ТБ в 64-разрядной системе, если вы не читаете или не записываете в эту память, она не резервирует для нее никакого физического пространства. На самом деле, он зарезервирует физическую память только для страниц, к которым вы прикоснулись из этого большого блока, а не для всего блока. И через "некоторое время неиспользования этой памяти" ее содержимое будет скопировано на диск, а базовая физическая память будет использована для чего-то другого.
Ответ 3
Это очень зависит от фактической используемой реализации malloc.
В Linux существует пороговое значение (MMAP_THRESHOLD
), позволяющее определить, откуда MMAP_THRESHOLD
память для данного запроса malloc()
.
Если запрашиваемая сумма меньше или равна MMAP_THRESHOLD
, запрос удовлетворяется либо путем извлечения его из так называемого "свободного списка", если какие-либо блоки памяти уже были free()
d. В противном случае "разрыв строки" программы (т.е. Конец сегмента данных) увеличивается, и память, выделенная программе этим процессом, используется для запроса.
В free()
освобожденный блок памяти добавляется в список свободных. Если в самом конце сегмента данных достаточно свободной памяти, разрывная линия (упомянутая выше) снова перемещается, чтобы уменьшить сегмент данных, возвращая избыточную память в ОС.
Если запрашиваемая сумма превышает MMAP_THRESHOLD
, ОС запрашивает отдельный блок памяти и снова возвращает его во время free()
.
Смотрите также https://linux.die.net/man/3/malloc для деталей.