此代码是否返回对堆栈上分配的变量的无效引用?要不然是啥:
void *f(size_t sz) {
return alloca(sz);
}
或者它是由 alloca 实现/编译器支持处理的特殊情况f(alloca(size), alloca(size))
?
此代码是否返回对堆栈上分配的变量的无效引用?要不然是啥:
void *f(size_t sz) {
return alloca(sz);
}
或者它是由 alloca 实现/编译器支持处理的特殊情况f(alloca(size), alloca(size))
?
alloca
在 的堆栈帧中分配空间f
。一旦函数返回(它不再“保留”),你就不能用它做任何有用的事情。
alloca() 函数在调用者的堆栈帧中分配 size 个字节的空间。当调用 alloca() 的函数返回给它的调用者时,这个临时空间会自动释放。
这:
void *f() {
char* pc4 = alloca(4);
...
}
正是这样:
void *f() {
char pc4[4];
...
}
在第二种情况下,您既不能在函数之外返回/使用 pc4 ,也不能在第一种情况下做同样的事情。
根据Linux手册页:
该
alloca()
函数在调用者的栈帧中分配空间,并返回一个指向分配块的指针。alloca()
当被调用的函数返回时,这个临时空间会自动释放。
这意味着,尝试访问由返回的内存f()
将导致未定义的行为,因为它在f()
返回时被释放。
是的,代码返回一个无效的指针。alloca
call 不能包装到函数中。如果您需要 wrap alloca
,则仅限于宏包装器。
正如其他人所说,它将被释放,我真的不明白你如何改变这种行为。如果您查看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) 无论 alloca 对堆栈指针做什么,都会在函数结束时rbp
被覆盖rsp
那么你能得到你所询问的行为(不编写汇编)吗?这是一个棘手的问题,我不知道,但似乎可能不是。
我自己从未使用过 alloca,但我在这里读到了“内联问题”: 为什么使用 alloca() 不被认为是好的做法?
“最令人难忘的错误之一......”的答案非常有趣。
因此,当函数超出范围时,内存肯定会被释放是不正确的。