В некоторых реализациях UNIX невозможно вызвать функцию free() в отношении блока памяти, выделенного с помощью memalign(), поскольку в реализации memalign() для выделения блока памяти используется функция malloc(), а затем возвращается указатель на адрес с соответствующем выравниванием в этом блоке. Реализация функции memalign() в библиотеке glibc от этого ограничения не страдает.
Как и функции в пакете malloc, функция alloca() выделяет память в динамическом режиме. Но вместо получения памяти в куче alloca() получает память из стека путем увеличения размера стекового фрейма. Это возможно потому, что вызываемая функция относится к тем, чей фрейм стека по определению находится на его вершине. Поэтому для расширения, которое возможно простым изменением значения указателя стека, доступно пространство выше фрейма.
#include
void *alloca(size_t
Возвращает указатель на выделенный блок памяти
В аргументе size указывается количество байтов, выделяемое в стеке.
Нам не нужно, а на самом деле мы не должны вызывать функцию free() для высвобождения памяти, выделенной с помощью функции alloca(). Точно так же невозможно использовать функцию realloc() для изменения блока памяти, выделенного с помощью alloca().
Хотя функция alloca() не является частью SUSv3, она предоставляется большинством реализаций UNIX, и поэтому ее можно считать достаточно портируемой.
В старых версиях glibc и в некоторых других реализациях UNIX (главным образом производных от BSD) для получения объявления функции alloca() требуется включение вместо
Если в результате вызова alloca() произойдет переполнение стека, поведение программы станет непредсказуемым. В частности, мы не получим в качестве возвращаемого значения NULL и не будем проинформированы о возникновении ошибки. (На самом деле при таких обстоятельствах мы можем получить сигнал SIGSEGV. Подробную информацию вы получите в разделе 21.3.)
Учтите, что alloca() нельзя использовать внутри списка аргументов функции, как в следующем примере:
func(x, alloca(size), z); /* НЕВЕРНО! */
Дело в том, что пространство стека, выделенное функцией alloca(), появится в середине пространства для аргументов функции (которые помещаются в фиксированные места внутри стекового фрейма). Вместо этого нужно воспользоваться следующим кодом:
void *y;
y = alloca(size);
func(x, y, z);
Применение функции alloca() для выделения памяти по сравнению с использованием malloc() имеет ряд преимуществ. Одно из них состоит в том, что выделение блоков памяти с alloca() происходит быстрее, чем с malloc(), поскольку первая реализуется компилятором как встроенный код, который устанавливает указатель стека напрямую. Кроме того, функция alloca() не требует поддержки списка свободных блоков.
Еще одно преимущество alloca() состоит в том, что выделяемая этой функцией память автоматически высвобождается при удалении стекового фрейма, то есть когда происходит возвращение из функции, вызвавшей alloca(). Это случается потому, что код, выполняемый в ходе возвращения из функции, переустанавливает значение регистра указателя стека на конец предыдущего фрейма (то есть, учитывая, что стек растет вниз, на адрес, находящийся непосредственно над началом текущего фрейма). Поскольку нам не нужно ничего делать для обеспечения того, чтобы высвобождаемая память очищалась от всех путей возвращения из функции, программирование некоторых функций существенно упрощается.
Функция alloca() может особенно пригодиться при использовании функции longjmp() (см. раздел 6.8) или siglongjmp() (см. подраздел 21.2.1) для выполнения нелокального перехода из обработчика сигнала. В этом случае очень трудно или даже невозможно избежать утечки памяти, если она выделяется для той функции, над которой осуществляется переход, с помощью функции malloc(). Для сравнения, функция alloca() позволяет полностью избежать подобной проблемы, поскольку, как только стек будет отмотан этими вызовами назад, выделенная память автоматически высвободится.
С использованием семейства функций malloc процесс может выделять и высвобождать память в куче в динамическом режиме. При рассмотрении реализации этих функций было показано, что в программах, неправильно обращающихся с блоками выделенной памяти, могут происходить различные неприятности. Кроме того, было отмечено, что для содействия обнаружению источника подобных ошибок доступно несколько отладочных средств.
Функция alloca() выделяет память в стеке. Эта память автоматически высвобождается при возвращении из функции, вызвавшей alloca().