В каких случаях полезно использовать alloca()?

Зачем вам когда-либо хотеть использовать alloca(), когда вы всегда можете выделить буфер фиксированного размера в стеке, достаточно большом для всех применений? Это не риторический вопрос...

6 ответов

Решение

Это может быть полезно, если размер буфера изменяется во время выполнения, или если вам это нужно только иногда: это будет занимать меньше места в стеке в целом, чем буфер фиксированного размера в каждом вызове. Особенно, если функция находится высоко в стеке или рекурсивна.

С помощью alloca() может быть разумным, когда вы не можете использовать malloc() (или же new в C++ или в другом распределителе памяти) надежно или вообще, но вы можете предположить, что в вашем стеке доступно больше места, то есть когда вы больше ничего не можете сделать.

Например, в glibc sgfault.c, у нас есть:

 /* This function is called when a segmentation fault is caught.  The system
    is in an unstable state now.  This means especially that malloc() might
    not work anymore.  */
static void
catch_segfault (int signal, SIGCONTEXT ctx)
{
    void **arr;

    /* ... */

    /* Get the backtrace.  */
    arr = alloca (256 * sizeof (void *));

    /* ... */
}

Возможно, вы захотите использовать его, если нет способа узнать максимальный размер, который вам может понадобиться во время компиляции.

Нужен ли вам другой вопрос - это не стандартно, и нет никакого способа определить, может ли это вызвать переполнение стека.

В каких случаях полезно использовать alloca()?

Единственный раз, когда я видел использование alloca, был в Open Dynamics Engine. AFAIK они выделяли ОГРОМНЫЕ матрицы с помощью этого (таким образом, скомпилированная программа могла требовать стека в 100 МБ), которые автоматически освобождались при возврате функции (для меня это выглядит как срыв со смарт-указателя). Это было довольно давно.

Хотя это было, вероятно, намного быстрее, чем new / malloc, я все же думаю, что это была плохая идея. Вместо вежливого запуска ОЗУ, программа могла аварийно завершить работу с переполнением стека (т.е. вводить в заблуждение), когда сцена стала слишком сложной для обработки. Неплохое поведение, IMO, особенно для физического движка, где вы можете легко ожидать, что кто-то бросит несколько тысяч кирпичей в сцену и увидит, что происходит, когда все они сталкиваются одновременно. Кроме того, вы должны были установить размер стека вручную - т.е. в системе с большим объемом оперативной памяти программа все равно будет ограничена размером стека.

буфер фиксированного размера в стеке, достаточно большой, чтобы соответствовать всем применениям? Это не риторический вопрос...

Если вам нужен буфер фиксированного размера для всех целей, вы также можете поместить его в статическую / глобальную переменную или использовать кучу памяти.

Никогда - это не является частью C++ и бесполезно в C. Однако вы не можете выделить "статический буфер в стеке" - статические буферы размещаются во время компиляции, а не в стеке.

Суть alloca(), конечно, в том, что он не имеет фиксированного размера, он находится в стеке и что он автоматически освобождается при выходе из функции. И C++, и C имеют лучшие механизмы для этого.

alloca() функция практически не нужна; в целях выделения памяти вы можете использовать malloc()/free() в C (или один из набора возможностей в C++) и достичь практически того же практического эффекта. Это имеет преимущество в том, что лучше справляется с меньшими размерами стека.

Однако я видел[1] одно законное (если хакерское!) Его использование: для обнаружения потенциального переполнения стека в Windows; если выделение (того количества отстойного пространства, к которому вы хотели получить доступ) не удалось, вы вышли, но у вас было достаточно места для изящного восстановления. Было завернуто в __try/__except чтобы он не падал и нуждался в дополнительных хитростях ассемблера, чтобы избежать проблем, связанных с gcc. Как я уже сказал, взломать. Но умный, который является единственным допустимым использованием для alloca() что я когда-либо видел

Но не делай этого. Лучше написать код, чтобы не нужны такие игры.


[1] Это было в Tcl 8.4 (и, возможно, в более ранних версиях Tcl). Это было удалено в более поздних версиях. Более поздние версии удалили это, потому что это было привередливым, очень хитрым и глубоко тревожащим. 8.6 использует реализацию стека механизма исполнения вместо такого рода фанки.

Другие вопросы по тегам