开发者

Why is alloca different from just creating a local variable?

开发者 https://www.devze.com 2023-04-01 11:03 出处:网络
I read that there is a funciton called alloca that allocates memory from the stack frame of the current function rather than the heap.The memory is automatically destroyed when the function exits.

I read that there is a funciton called alloca that allocates memory from the stack frame of the current function rather than the heap. The memory is automatically destroyed when the function exits.

What is the point of this, and how is it any different from just crating an array开发者_运维问答 of a structure or a local variable within the function? They would go on the stack and would be destroyed at the end of the function as well.

PS: I saw the other alloca question and it didn't answer how these two things are different :)


When you use alloca, you get to specify how many bytes you want at run time. With a local variable, the amount is fixed at compile time. Note that alloca predates C's variable-length arrays.


With alloca you can create a dynamic array (something that normally requires malloc) AND it's VERY fast. Here there are the advantages and disadvantages of GCC alloca:

http://www.gnu.org/s/hello/manual/libc/Variable-Size-Automatic.html#Variable-Size-Automatic


I think the following are different:

void f()
{
  {
    int x;
    int * p = &x;
  }
  // no more x
}

void g()
{
  {
    int * p = alloca(sizeof(int));
  }
  // memory still allocated
}


Until gcc and C99 adopted Variable-length arrays, alloca offered significantly more power than simple local variables in that you could allocate arrays whose length is not known until runtime.

The need for this can arise at the boundary between two data representations. In my postscript interpreter, I use counted strings internally; but if I want to use a library function, I have to convert to a nul-terminated representation to make the call.

OPFN_ void SSsearch(state *st, object str, object seek) {
    //char *s, *sk;
    char s[str.u.c.n+1], sk[seek.u.c.n+1]; /* VLA */

    //// could also be written:
    //char *s,*sk;
    //s = alloca(str.u.c.n+1);
    //sk = alloca(seek.u.c.n+1);

    char *r;
    //if (seek.u.c.n > str.u.c.n) error(st,rangecheck);
    //s = strndup(STR(str), str.u.c.n);
    //sk = strndup(STR(seek), seek.u.c.n);
    memcpy(s, STR(str), str.u.c.n); s[str.u.c.n] = '\0';
    memcpy(sk, STR(seek), seek.u.c.n); sk[seek.u.c.n] = '\0';
    r = strstr(s, sk);
    if (r != NULL) { int off = r-s;
        push(substring(str, off + seek.u.c.n, str.u.c.n - seek.u.c.n - off)); /* post */
        push(substring(str, off, seek.u.c.n)); /* match */
        push(substring(str, 0, off)); /* pre */
        push(consbool(true));
    } else {
        push(str);
        push(consbool(false));
    }
    //free(sk);
    //free(s);
}

There is also a dangerous usage of alloca, which is easily avoided by prefering VLAs. You cannot use alloca safely within the argument list of a function call. So don't ever do this:

char *s = strcpy(alloca(strlen(t)+1, t);

That's what VLAs are for:

char s[strlen(t)+1];
strcpy(s,t);
0

精彩评论

暂无评论...
验证码 换一张
取 消