我已经阅读了很多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的实际使用吗?同样假设这个例子,由于某种原因,我想要在堆栈上分配值
答案 0 :(得分:18)
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 :(得分:1)
alloca
完全可由malloc
和free
替换。这是一个更多的工作,但除非你非常小心,这是必不可少的。几乎所有使用alloca
或C99 vla的代码都容易受到堆栈溢出攻击,并且在许多实现中,它们可能导致权限提升。没有可移植的方法来了解堆栈的大小或剩余多少堆栈空间(或者编译器的内部使用或进一步的函数调用可能需要超出请求大小的开销),所以你可以做的唯一合理的事情是使vla / alloca
安全对你支持的数据大小施加极小的人为限制(例如几kb)。此时您可能只是使用普通的非可变长度自动对象...