Я считал довольно много мест это alloca
является устаревшим и не должен использоваться, и Массивы Переменной длины должны использоваться вместо этого.
Мой вопрос - это: alloca
абсолютно заменимый массивами переменной длины?
В моем конкретном экземпляре у меня есть что-то, что похоже на это:
typedef struct {
int *value;
size_t size;
} some_type;
void SomeExternalFunction(some_type);
...
void foo(){
//What I thought to do
some_type bar;
bar.value=alloca(sizeof(int)*10);
SomeExternalFunction(bar);
//what should be done without alloca
some_type fizz;
int tmp[10];
fizz.value=tmp;
SoemExternalFunction(fizz);
}
Я пропускаю что-то, или действительно ли это - фактическое хорошее использование alloca? Также предположите для этого примера, что по некоторым причинам я хочу, чтобы значение было выделено на стеке
Существует важное различие между VLA и alloca: функция memory alloca () возвращает значение , пока сохраняется текущая функция . Время жизни памяти, занимаемой VLA, является действительным, пока идентификатор VLA остается в области видимости . Вы можете, например, выделить память a () в цикле и использовать память вне цикла, VLA исчезнет, потому что идентификатор выходит за пределы области действия, когда цикл завершается. Это означает, что вы можете сделать это с помощью alloca () и достаточно места в стеке:
typedef struct node { int data; struct node *next; };
void fun()
{
struct node *n=0;
int d;
/* Now we are building a single-linked list on the stack! */
while(d=get_something()) {
struct node *x=alloca(sizeof(*x));
x->next=n;
x->data=d;
n=x;
}
do_something_with(n);
} // and the whole thing is deleted here..
Вы не можете сделать это с помощью VLA.
alloca
полностью заменяется malloc
и free
. Это немного больше работы, но если вы не очень осторожны, это необходимо. Почти весь код, использующий alloca
или C99 vla's, уязвим для атак переполнения стека, и во многих реализациях они могут привести к повышению привилегий. Нет никакого переносимого способа узнать, насколько велик стек или сколько места в стеке осталось (или сколько накладных расходов сверх запрашиваемого размера может потребоваться для внутреннего использования компилятором или дальнейших вызовов функций), поэтому единственное разумное, что вы можете сделать для обеспечения безопасности vla's/alloca
- это наложить очень небольшие искусственные ограничения на размер поддерживаемых данных (например, несколько кб). С таким же успехом вы могли бы просто использовать обычные автоматические объекты непеременной длины...