为啥不能在函数参数列表中使用 alloca?

Posted

技术标签:

【中文标题】为啥不能在函数参数列表中使用 alloca?【英文标题】:Why can not alloca be used in function argument list?为什么不能在函数参数列表中使用 alloca? 【发布时间】:2017-06-14 15:37:33 【问题描述】:

引用BUGS 部分的第二段,来自alloca(3) 的手册页

在许多系统上,alloca() 不能在函数调用的参数列表中使用,因为堆栈 alloca() 保留的空间将出现在堆栈中函数参数空间的中间。

我没有看到这是怎么发生的。以如下代码为例:

void f(int a, void * b, int c);

int
main(void)

    f(1, alloca(100), 2);

根据我的理解,allocamain 的堆栈帧向下扩展 100 个字节(通过修改堆栈指针寄存器),然后传递指向该堆栈内存块的指针(以及 2 个 ints)在f 的堆栈帧上。所以分配的空间不应该在abc的中间,实际上它应该在不同的帧上(在这种情况下是在main的帧上)。

那么这里有什么误解呢?

【问题讨论】:

【参考方案1】:

首先,请立即注意alloca is not standard。它是对平台的扩展,它希望通过潜在地动态消耗自动变量空间来为程序员提供更多方式来吊死自己,以提高基于其他技术(堆等)的慢速动态内存分配器的速度。 (是的,我的意见,但其中有很多真相)。

也就是说,考虑一下:

你以前写过编译器吗? There is no standard guarantee of evaluation order of function arguments。因此,假设某个平台选择构建activation record 以调用f,最终将以下内容从右到左(他们的选择)推入激活堆栈:

    将 2 推入激活记录堆栈空间。 执行alloca(100),这会消耗同一个堆栈,该堆栈保存由另外100 个char 构建的调用激活记录。 将 (2) 的结果 void* 推入激活记录堆栈空间。 将 1 推入激活记录堆栈空间。 调用call f,将main中的返回地址推入激活记录堆栈空间。

现在,把你自己想象成函数f。您希望在哪里找到函数的第三个参数?嗯……

这只是一个示例,说明如何将alloca 空间扔到可能导致问题的地方。

【讨论】:

third parameter 是否指向12?为什么在函数f 里面找不到第三个参数?你能更详细地解释一下吗?因为编译器不知道alloca分配的内存有多少被占用了?

以上是关于为啥不能在函数参数列表中使用 alloca?的主要内容,如果未能解决你的问题,请参考以下文章

C语言中,数组名作为函数参数,属于啥传递,为啥?

调用函数时为啥形参的值不能传给实参

为啥这个 CMake 脚本找到“alloca”但仍然失败?

golang函数中的参数为啥不支持默认值

C语言中如何实现可变参函数

形参和实参的区别