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

Posted

技术标签:

【中文标题】为啥 alloca 与创建局部变量不同?【英文标题】:Why is alloca different from just creating a local variable?为什么 alloca 与创建局部变量不同? 【发布时间】:2011-11-07 16:47:51 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

【参考方案2】:

我认为以下是不同的:

void f()

  
    int x;
    int * p = &x;
  
  // no more x


void g()

  
    int * p = alloca(sizeof(int));
  
  // memory still allocated

【讨论】:

我会试一试,这将是一个有趣的区别 :) 你可能是对的,因为我认为 alloca 提到了函数范围。 很可能在这两种情况下仍然分配了内存。 x name 不再可用,但它所代表的内存仍分配给堆栈——编译器通常不会在每次进入或离开新范围时调整堆栈指针。 @Rob:好的,增加示例以在块之后添加更多声明。在第一种情况下,您会为x 重用内存,而在第二种情况下,您不会...【参考方案3】:

当您使用alloca 时,您可以指定在运行时需要多少字节。使用局部变量,数量在编译时是固定的。请注意,alloca 早于 C 的可变长度数组。

【讨论】:

【参考方案4】:

使用alloca,您可以创建一个动态数组(通常需要malloc),而且速度非常快。这里有GCCalloca的优缺点:

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

【讨论】:

“GCC alloca”是什么意思? alloca 通常定义为编译器内在函数。通常它不是“标准”功能。我认为在 GCC 中也是如此。例如看到这个:linux.die.net/man/3/alloca

以上是关于为啥 alloca 与创建局部变量不同?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的线程函数中的局部变量会被其他线程中断?

成员变量与局部变量

成员变量与局部变量的区别

成员变量与局部变量的区别

Python--局部变量和全局变量

为啥当我在函数中声明一个名称为全局数组的局部数组时,bash 会引发未绑定变量警告?