此代码是否返回对堆栈上分配的变量的无效引用?或者是:
void *f(size_t sz) {
return alloca(sz);
}
或者它是一个特殊的情况,是由分配实现/编译器支持像f(alloca(size), alloca(size))
将是处理?
alloca
在f
的堆栈帧中分配空间。一旦函数返回,你就不能用它做任何有用的事情了(它不再是"保留的"了)。
alloca()函数在堆栈帧中分配大小字节的空间打电话的人。该临时空间在执行命令时自动释放调用alloca()的函数返回给调用者。
this:
void *f() {
char* pc4 = alloca(4);
...
}
就是这样:
void *f() {
char pc4[4];
...
}
在第二种情况下,您既不能在函数外部返回/使用pc4,也不能在第一种情况下这样做。
是的,代码返回一个无效的指针。alloca
调用不能包装成函数。如果您需要包装alloca
,则仅限于宏包装器。
根据Linux手册页:
alloca()
函数在对象的堆栈框架中分配空间调用者,并返回指向已分配块的指针。这个临时当alloca()
这意味着,试图访问由f()
返回的内存将导致未定义的行为,因为当f()
返回时它将被释放。
正如其他人所说,它将被释放,我真的不知道如何改变这种行为。如果您查看alloca
如何在amd-64上编译:
pushq %rbp
movq %rsp, %rbp
subq $144, %rsp
movq %rsp, %rax
addq $15, %rax
shrq $4, %rax
salq $4, %rax
leave
ret
你看到1) Alloca实际上不是一个函数调用(因为,正如你所说,它必须以不同的方式处理堆栈!)
2)当rbp
覆盖rsp
那么可以你得到你所要求的行为(不编写汇编)吗?这是一个棘手的问题,我不知道,但看起来可能不是。
我自己从来没有使用过alloca,但是我在这里读到"内联问题":为什么使用alloca()不被认为是好的实践?
答案"最令人难忘的bug之一…"非常有趣。
因此,当函数超出作用域时,内存并不一定会被释放。