alloca是完全可替换的吗?

alloca是完全可替换的吗?,c,arrays,alloca,C,Arrays,Alloca,我读过很多地方,认为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;

我读过很多地方,认为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之间有一个重要区别:只要当前函数持续存在,内存alloca()返回的值就有效。只要VLA的标识符仍在范围内,VLA占用的内存的生存期就是有效的。例如,您可以在循环中alloca()内存并使用循环外的内存,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..

你不能用VLAs来做这件事。

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

这实际上不是可变长度数组。。。正如您指定的恒定长度。而且。。。即使它是一个可变长度,我也不知道alloca在这里为您带来了什么,只是让代码的意图变得更加模糊。(显然,如果您使用的编译器不支持可变长度数组,那么您在这两者之间没有选择)另请参见:(根据标题可能是重复的,但我觉得您确实想问一些其他问题……但不知道是什么)FWIW:这将是对两者的一个很好的回答,这是关于差异的一个很好的回答,但您可能还想注意,
alloca
的行为本质上是实现定义的,因为它没有在任何(当前)标准中指定。顺便说一下,有一种方法可以对VLAs执行相同的操作:使函数递归,并在最深层调用(n)。:-)实际上,我有一个实际的用途,我还没有实现:一个轻量级的
/lib/ld实现。因此,
在堆栈上执行动态链接,以避免将
malloc
开销带入不使用它的小程序。最后,当且仅当
libdl
未链接时,它将展开并丢弃所有动态链接数据;否则,它将从递归的最深层调用
\u start
。@R:我记得在某个地方读到,当当前大括号部分离开时,WARE/are alloca将被释放。因此,检查手册可能是一个好主意。@R:Chicken Scheme使用类似的技术来执行其分配:程序被编译成一组函数,这些函数存在带有尾部调用的调用continuations,这意味着所有分配都可能发生在堆栈上。垃圾收集器将在堆栈已满时将活动对象移动到堆中,并通过执行“返回”来倒回堆栈。堆将完全替换堆栈。不可以。在实时上下文中,必须只使用堆栈,避免堆内存(malloc/free/new),因为当系统需要将页交换到磁盘时,分配可能会使线程停止数秒。@diemo:这两种说法都不正确。使用堆栈可能会导致分页(如果堆栈指针跨入新页,而该页尚未实例化或被调出或丢弃),并且使用分配的(“堆”)内存不需要能够导致交换(例如,如果没有磁盘)。