为什么不能在函数参数列表中使用 alloca?
Why can not alloca be used in function argument list?
引用 BUGS
部分的第二段,来自 alloca(3)
的联机帮助页
On many systems alloca()
cannot be used inside the list of arguments of a function call, because the stack
space reserved by alloca()
would appear on the stack in the middle of the space for the function arguments.
我没看到这是怎么发生的。以下面的代码为例:
void f(int a, void * b, int c);
int
main(void)
{
f(1, alloca(100), 2);
}
根据我的理解,alloca
将 main
的堆栈帧向下扩展 100 个字节(通过修改堆栈指针寄存器),然后是指向该堆栈内存块的指针(以及 2 int
s) 在 f
的堆栈帧上传递。所以分配的 space 不应该在 a
、b
或 c
的中间,实际上它应该在不同的框架上(在 [= 的框架上) 16=] 在这种情况下)。
那么这里的误会是什么?
首先,请立即注意 alloca
is not standard。它是对平台的扩展,希望通过潜在地动态使用自动变量 space 为程序员提供更多方式来挂起自己,以提高基于其他技术(堆等)的慢速动态内存分配器的速度。 (是的,我的意见,但其中有很多道理)。
也就是说,考虑一下:
你以前写过编译器吗? There is no standard guarantee of evaluation order of function arguments. So just suppose some platform chose to build the activation record 通过最终将以下内容从右到左(他们的选择)推入激活堆栈来调用 f
:
- 将 2 压入激活记录栈 space.
- 执行
alloca(100)
,它吸取 相同的堆栈 保存由另外 100 char
. 建立的呼叫激活记录
- 将(2)的结果a
void*
压入激活记录栈space.
- 将 1 压入激活记录堆栈 space。
- 调用
call f
,将main
中的return地址压入激活记录栈space。
现在,把你自己想象成函数f
。您希望在哪里找到函数的第三个参数?嗯....
这只是一个例子,说明如何将 alloca
space 扔到可能导致问题的地方。
引用 BUGS
部分的第二段,来自 alloca(3)
On many systems
alloca()
cannot be used inside the list of arguments of a function call, because the stack space reserved byalloca()
would appear on the stack in the middle of the space for the function arguments.
我没看到这是怎么发生的。以下面的代码为例:
void f(int a, void * b, int c);
int
main(void)
{
f(1, alloca(100), 2);
}
根据我的理解,alloca
将 main
的堆栈帧向下扩展 100 个字节(通过修改堆栈指针寄存器),然后是指向该堆栈内存块的指针(以及 2 int
s) 在 f
的堆栈帧上传递。所以分配的 space 不应该在 a
、b
或 c
的中间,实际上它应该在不同的框架上(在 [= 的框架上) 16=] 在这种情况下)。
那么这里的误会是什么?
首先,请立即注意 alloca
is not standard。它是对平台的扩展,希望通过潜在地动态使用自动变量 space 为程序员提供更多方式来挂起自己,以提高基于其他技术(堆等)的慢速动态内存分配器的速度。 (是的,我的意见,但其中有很多道理)。
也就是说,考虑一下:
你以前写过编译器吗? There is no standard guarantee of evaluation order of function arguments. So just suppose some platform chose to build the activation record 通过最终将以下内容从右到左(他们的选择)推入激活堆栈来调用 f
:
- 将 2 压入激活记录栈 space.
- 执行
alloca(100)
,它吸取 相同的堆栈 保存由另外 100char
. 建立的呼叫激活记录
- 将(2)的结果a
void*
压入激活记录栈space. - 将 1 压入激活记录堆栈 space。
- 调用
call f
,将main
中的return地址压入激活记录栈space。
现在,把你自己想象成函数f
。您希望在哪里找到函数的第三个参数?嗯....
这只是一个例子,说明如何将 alloca
space 扔到可能导致问题的地方。