Является ли alloca полностью заменяемой? - PullRequest
8 голосов
/ 15 августа 2010

Я прочитал довольно много мест, которые 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? Также предположим для этого примера, что по какой-то причине я хочу, чтобы значение было выделено в стеке

Ответы [ 2 ]

18 голосов
/ 15 августа 2010

Существует важное различие между VLA и alloca: возврат памяти alloca () действителен , пока текущая функция сохраняется .Срок службы памяти, занимаемой VLA, действителен, пока идентификатор VLA остается в области действия .Например, вы можете выделить память в цикле и использовать память вне цикла , 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.

1 голос
/ 16 августа 2010

alloca полностью заменяется на malloc и free.Это немного больше работы, но если вы не очень осторожны, это важно.Почти весь код, использующий alloca или C99 vla, уязвим для атак переполнения стека, и во многих реализациях они могут привести к повышению привилегий.Нет никакого портативного способа узнать, какой размер стека или сколько места осталось в стеке (или какая дополнительная нагрузка сверх запрошенного размера может потребоваться для внутреннего использования компилятором или для дальнейших вызовов функций), поэтому единственное разумное, что вы можете сделатьmake vla's / alloca safe накладывает чрезвычайно малые искусственные ограничения на размер данных, которые вы поддерживаете (например, несколько килобайт).В этот момент вы могли бы просто использовать простые автоматические объекты не переменной длины ...

...