10

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 的实际使用?还假设对于这个例子,由于某种原因,我希望在堆栈上分配值

4

2 回答 2

24

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 无法做到这一点。

于 2010-08-15T19:36:23.770 回答
-3

alloca完全可以用mallocand代替free。这是一个多一点的工作,但除非你非常小心,否则它是必不可少的。几乎所有使用alloca或 C99 vla 的代码都容易受到堆栈溢出攻击,并且在许多实现中,它们可能导致特权提升。没有可移植的方法来知道堆栈有多大或剩余多少堆栈空间(或者编译器的内部使用或进一步的函数调用可能需要超出请求大小的多少开销),所以你可以做的唯一合理的事情是使 vla's/ allocasafe 对您支持的数据大小(例如几 kb)施加了极小的人为限制。在这一点上,您还不如只使用普通的非可变长度自动对象......

于 2010-08-16T05:41:57.030 回答