Is alloca completely replaceable?

2019-04-23 07:08发布

I've read quite a few places that alloca is obsolete and should not be used and Variable Length Arrays should be used instead.

My question is this: Is alloca completely replaceable by variable length arrays?

In my particular instance I have something that looks like this:

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);
}

Am I missing something or is this an actual good use of alloca? Also assume for this example that for some reason I want for the value to be allocated on the stack

标签: c arrays alloca
2条回答
我想做一个坏孩纸
2楼-- · 2019-04-23 07:27

alloca is completely replaceable by malloc and free. It's a little more work but unless you're very careful, it's essential. Nearly all code using alloca or C99 vla's is vulnerable to stack overflow attacks, and in many implementations, they can lead to privilege elevation. There's no portable way to know how large the stack is or how much stack space is left (or how much overhead beyond the requested size might be needed for the compiler's internal use or further function calls), so the only reasonable thing you can do to make vla's/alloca safe is impose extremely small artificial limits on the size of data you support (e.g. a few kb). At this point you might as well just be using plain non-variable-length automatic objects...

查看更多
别忘想泡老子
3楼-- · 2019-04-23 07:34

There is an important difference between VLA's and alloca: The memory alloca() returns is valid as long as the current function persists. The lifetime of the memory occupied by a VLA is valid as long as the VLA's identifier remains in scope. You can alloca() memory in a loop for example and use the memory outside the loop, a VLA would be gone because the identifier goes out of scope when the loop terminates. This means, you can do this with alloca() and enough stack space:

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..

You can't do this with VLAs.

查看更多
登录 后发表回答