MALLOC(3) | Руководство программиста Linux | MALLOC(3) |
malloc, free, calloc, realloc - распределяет и освобождает динамическую память
#include <stdlib.h>
void *malloc(size_t size); void free(void *ptr); void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); void *reallocarray(void *ptr, size_t nmemb, size_t size);
Требования макроса тестирования свойств для glibc (смотрите feature_test_macros(7)):
reallocarray(): _GNU_SOURCE Начиная с glibc 2.29: _DEFAULT_SOURCE В glibc 2.28 и старее: _GNU_SOURCE
Функция malloc() распределяет size байтов и возвращает указатель на распределённую память. Память при этом не инициализируется. Если значение size равно 0, то malloc() возвращает или NULL, или уникальный указатель, который можно без опасений передавать free().
Функция free() освобождает место в памяти, указанное в ptr, которое должно быть получено ранее вызовом функции malloc(), calloc() или realloc(). Иначе (или если вызов free(ptr) уже выполнялся) дальнейшее поведение не определено. Если значение ptr равно NULL, то не выполняется никаких действий.
Функция сalloc() распределяет память для массива размером nmemb элементов по size байтов каждый и возвращает указатель на распределённую память. Данные в выделенной памяти при этом обнуляются. Если значение nmemb или size равно 0, то calloc() возвращает NULL или уникальный указатель, который можно без опасений передавать free(). Если перемножение nmemb и size приводит к целочисленному переполнению, то calloc() возвращает ошибку. Это отличает её от malloc(), которая не обнаруживает целочисленное переполнение и возвращает блок памяти неправильного размера:
malloc(nmemb * size);
Функция realloc() меняет размер блока памяти, на который указывает ptr, на размер, равный size байт. Содержимое памяти не будет изменено от начала области в пределах наименьшего из старого и нового размеров. Если новый размер больше старого, то добавленная память не будет инициализирована. Если значение ptr равно NULL, то вызов эквивалентен malloc(size) для всех значений size; если значение size равно нулю и ptr не равно NULL, то вызов эквивалентен free(ptr). Если только значение ptr не равно NULL, то должно быть возвращено ранее полученное значение от malloc(), calloc() или realloc(). Если область была перемещена, то выполняется free(ptr).
Функция reallocarray() изменяет размер блока памяти, на который указывает ptr, таким образом, чтобы он смог вместить массив из nmemb элементов, каждый из которых занимает size байт. Она эквивалентна вызову
realloc(ptr, nmemb * size);
Однако в отличие от вызова realloc(), функция reallocarray() безопасно завершается ошибкой в случае возникновения переполнения умножения. Если это происходит, то reallocarray() возвращает NULL, присваивает errno значение ENOMEM и оставляет первоначальный блок памяти в неизменном виде.
Функции malloc() и calloc() возвращают указатель на распределённую память, выровненную должным образом для любого встроенного типа. При ошибке возвращается NULL. Значение NULL также может быть получено при успешной работе вызова malloc(), если значение size равно нулю, или calloc() — если значение nmemb или size равно нулю.
Функция free() ничего не возвращает.
Функция realloc() возвращает указатель на новую распределённую память, выровненную должным образом для любого встроенного типа. Возвращаемый указатель может отличаться от ptr, или равняться NULL, если запрос завершился с ошибкой. Если значение size было равно нулю, то возвращается либо NULL, либо указатель, который может быть передан free(). Если realloc() завершилась с ошибкой, то начальный блок памяти остаётся нетронутым: он не освобождается или перемещается.
При успешном выполнении функция reallocarray() возвращает указатель на новую выделенную память. При ошибке возвращается NULL, а первоначальный блок памяти не изменяется.
Функции calloc(), malloc(), realloc() и reallocarray() могут завершаться со следующей ошибкой:
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение |
malloc(), free(), calloc(), realloc() | Безвредность в нитях | MT-Safe |
malloc(), free(), calloc(), realloc(): POSIX.1-2001, POSIX.1-2008, C89, C99.
Функция reallocarray() является нестандартным расширением, впервые появилась в OpenBSD 5.6 и FreeBSD 11.0.
По умолчанию, Linux придерживается оптимистичной стратегии распределения памяти. Это означает, что когда malloc() возвращает значение не NULL, то нет никаких гарантий, что память в действительности доступна. Если обнаружится, что системе не хватает памяти, то один или несколько процессов будут завершены OOM. Дополнительную информацию можно получить из описания /proc/sys/vm/overcommit_memory и /proc/sys/vm/oom_adj в proc(5) и файле из исходного кода ядра Linux Documentation/vm/overcommit-accounting.rst.
Обычно, malloc() выделяет память из кучи и подгоняет размер кучи соответствующим образом с помощью sbrk(2). Если выделяемый блок памяти больше чем MMAP_THRESHOLD байт, то реализация malloc() в glibc выделяет память с помощью mmap(2) в виде частного анонимного отображения. По умолчанию, значение MMAP_THRESHOLD равно 128 КБ, но его можно изменить с помощью mallopt(3). До Linux 4.7 на выделения, выполняемые с помощью mmap(2), не влияет ограничитель ресурса RLIMIT_DATA; начиная с Linux 4.7 это ограничение также применяется к выделениям, созданным с помощью mmap(2).
Внутри данных функций для защиты от повреждений выделяемых структур данных управления памятью, используются мьютексы. В многонитевых приложениях, в которых нити одновременно выделяют и освобождают память, может возникнуть конфликт за обладание этими мьютексами. Чтобы расширить обработку выделения памяти в многонитевых приложениях библиотека glibc создаёт дополнительные области выделения памяти (memory allocation arenas), если обнаруживается конфликт. Каждая область представляет собой большой кусок памяти, который внутренне выделен системой (с помощью brk(2) или mmap(2)) и управляется своими собственными мьютексами.
Стандарт SUSv2 требует, чтобы функции malloc(), calloc() и realloc() при ошибках присваивали значение ENOMEM переменной errno. Glibc допускает, что это уже реализовано (и версии glibc этих функций делают это); если вы используете свою реализацию функции malloc, которая не изменяет errno, то некоторые функции библиотеки могут закончить работу с ошибкой без указания причины в errno.
Аварийные ситуации в malloc(), calloc(), realloc() или free() почти всегда связаны с повреждением кучи, например, с переполнением больших распределённых участков памяти или освобождением одного и того же указателя дважды.
Реализация malloc() настраивается с помощью переменных окружения; подробности смотрите в mallopt(3).
valgrind(1), brk(2), mmap(2), alloca(3), malloc_get_state(3), malloc_info(3), malloc_trim(3), malloc_usable_size(3), mallopt(3), mcheck(3), mtrace(3), posix_memalign(3)
Информацию о реализации в библиотеке GNU C смотрите в https://sourceware.org/glibc/wiki/MallocInternals.
2019-03-06 | GNU |