GNU libc的 实现alloca()
如下:
# define alloca(size) __builtin_alloca (size)
它使用内置的编译器,因此它完全取决于编译器如何实现它。更具体地说,它取决于堆栈的处理方式,这恰好是一个机器和依赖于 ABI 的数据结构。
让我们来看看一个具体的案例。在我的机器上,这是以下组件 alloca(100000000000L)
:
0e9b: movabsq $-100000000016, %rax ; * Loads (size + 16) into rax.
0ea5: addq %rax, %rsp ; * Adds it to the top of the stack.
0ea8: movq %rsp, -48(%rbp) ; * Temporarily stores it.
0eac: movq -48(%rbp), %rax ; * These five instructions round the
0eb0: addq $15, %rax ; value stored to the next multiple
0eb4: shrq $4, %rax ; of 0x10 by doing:
0eb8: shlq $4, %rax ; rax = ((rax+15) >> 4) << 4
0ebc: movq %rax, -48(%rbp) ; and storing it again in the stack.
0ec0: movq -48(%rbp), %rax ; * Reads the rounded value and copies
0ec4: movq %rax, -24(%rbp) ; it on the previous stack position.
gcc-4.2 -g test.c -o test
使用以下程序编译 :
有东西可以参考,现在可以回答您的问题:
在堆栈遇到堆段之前,它是否会分配尽可能多的字节?
它只是按请求的字节数盲目地增加堆栈。根本不执行边界检查,因此堆栈指针和返回值现在都可能位于非法位置。尝试从返回的值读取/写入(或压入堆栈)将导致SIGSEGV
.
它返回什么,在调用 main 之前指向堆栈顶部之后的第一个字节的指针?
它返回一个指向已分配内存的第一个字节的指针。
返回后的堆栈指针与调用alloca()
之前的堆栈指针不同alloca()
吗?
是的,见上面的解释。此外,当调用的函数alloca
返回时,堆栈将恢复到前一帧并再次可用。