为什么alloca与创建局部变量不同?

时间:2011-08-31 14:52:12

标签: c unix

我读到有一个名为alloca的函数,它从当前函数的堆栈帧而不是堆中分配内存。当函数退出时,内存会自动销毁。

这有什么意义,它与仅在函数中创建结构数组或局部变量有什么不同?它们会进入堆栈并在函数结束时被销毁。

PS:我看到了另一个alloca问题,并没有回答这两个方面有何不同:)

4 个答案:

答案 0 :(得分:9)

使用alloca时,可以指定运行时所需的字节数。使用局部变量,金额在编译时固定。请注意,alloca早于C的可变长度数组。

答案 1 :(得分:6)

使用alloca,你可以创建一个动态数组(通常需要malloc的东西)并且它非常快。这里有GCC alloca的优点和缺点:

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

答案 2 :(得分:2)

我认为以下是不同的:

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

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

答案 3 :(得分:1)

在gcc和C99采用可变长度数组之前,alloca比简单局部变量提供了更多的功能,因为你可以分配长度在运行时才知道的数组。

对此的需求可能出现在两个数据表示之间的边界处。在我的postscript解释器中,我在内部使用计数字符串;但如果我想使用库函数,我必须转换为以空终止的表示来进行调用。

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

还有alloca的危险用法,通过优先选择VLA可以轻松避免。您不能在函数调用的参数列表中安全地使用alloca。所以不要这样做:

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

这就是VLA的用途:

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