4

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

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

我没有看到这将如何发生。以以下代码为例:

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

int
main(void)
{
    f(1, alloca(100), 2);
}

根据我的理解,alloca将堆栈帧向下扩展main100 个字节(通过修改堆栈指针寄存器),然后将指向该堆栈内存块的指针(连同 2int秒)在堆栈帧上传递给f. 所以分配的空间不应该在a,b或者的中间c,实际上它应该在不同的框架上(main在这种情况下是在框架上)。

那么这里有什么误解呢?

4

1 回答 1

7

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

也就是说,考虑一下:

你以前写过编译器吗?函数参数的评估顺序没有标准保证。因此,假设某个平台选择通过最终将以下内容从右到左(他们的选择)推入激活堆栈来构建调用的激活记录:f

  1. 将 2 推入激活记录堆栈空间。
  2. Performs alloca(100),它吸收了同一个堆栈,该堆栈保存了另外 100 个正在构建的调用激活记录char
  3. 将 (2) 的结果 a 推void*入激活记录堆栈空间。
  4. 将 1 推入激活记录堆栈空间。
  5. 调用call f它,将返回地址main压入激活记录堆栈空间。

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

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

于 2017-01-29T10:19:24.827 回答