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

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

编译器通过使用 `__chkstk()` 函数在调整栈指针之前探测内存,从而确保栈的安全性。这防止了大尺寸的栈分配“跳过”保护页(guard page),进而避免触发栈溢出。 该机制同样适用于标准局部变量和通过 `_alloca()` 进行的动态分配。当调用 `_alloca()` 时,编译器会在执行用于分配空间的 `sub rsp` 指令之前,插入一个对 `__chkstk()` 的调用,以探测请求的内存大小。因此,无论是初始的局部栈帧设置,还是后续的 `_alloca()` 调用,都会统一使用 `__chkstk()` 来维护栈的完整性。

Hacker News 最新 | 过往 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 `alloca` 这类函数是如何在栈上分配内存的? (devblogs.microsoft.com/oldnewthing) 6 点,由 ingve 发布于 1 小时前 | 隐藏 | 过往 | 收藏 | 讨论 | 帮助 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 加入 YC | 联系 搜索:
相关文章

原文

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