像 alloca 这样的函数是如何从栈上分配内存的?
How do functions like alloca allocate memory from the stack?

原始链接: https://devblogs.microsoft.com/oldnewthing/20260817-00/?p=112617

编译器通过使用 `__chkstk()` 函数在分配空间前探测内存,确保了栈的安全性,从而防止大型栈分配绕过防护页。该机制既适用于标准的局部变量帧,也适用于通过 `alloca()` 进行的动态分配。 当调用 `alloca()` 时,它会触发对 `__chkstk()` 的调用,在调整栈指针之前探测所需的内存。正如所提供的 x86-64 汇编代码所示,该过程涉及两次对 `__chkstk()` 的独立调用:一次用于验证初始局部栈帧,另一次用于验证 `alloca()` 请求的额外内存。这种对探测函数的一致使用,确保了无论内存如何分配,栈溢出保护始终处于激活状态。

抱歉。
相关文章

原文

A little while ago, I talked about how compilers ensure that large stack allocations do not skip over the guard page. Shawn Van Ness was curious how this works with _alloca. “Does it do the necessary _chkstk() probing?”

Yes, the _alloca() function calls the same _chkstk() function to probe the stack before adjusting the stack pointer for the allocated memory.

Here’s an artificial example:

#include <malloc.h>

void consume(void*,void*);

void f(int n)
{
    char buffer[16384];
    consume(alloca(n), buffer);
}

On x86-64, this results in

        push    rbp
        mov     eax, 16416          ; probe for local frame
        call    __chkstk
        sub     rsp, rax            ; create local frame

        lea     rbp, [rsp+32]

        movsxd  rax, ecx            ; n
        lea     rcx, [rax+15]       ; round up to multiple of 16
        and     rcx, -16

        mov     rax, rcx            ; special __chkstk calling convention
        call    __chkstk
        sub     rsp, rcx            ; allocate n bytes

        lea     rdx, [rbp]          ; rdx -> buffer
        lea     rcx, [rsp+32]       ; rcx -> alloca'd memory
        call    consume

        lea     rsp, [rbp+16384]    ; clean up local frame
        pop     rbp
        ret     0

Observe that the same __chkstk function is used both for performing the initial stack probe when creating the local frame as well as for the alloca().

联系我们 contact @ memedata.com