我读到有一个名为alloca的函数,它从当前函数的堆栈帧而不是堆中分配内存。当函数退出时,内存会自动销毁。
这有什么意义,它与仅在函数中创建结构数组或局部变量有什么不同?它们会进入堆栈并在函数结束时被销毁。
PS:我看到了另一个alloca问题,并没有回答这两个方面有何不同:)
答案 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);