【问题标题】:What's up with gcc's handling of alloca?gcc 对 alloca 的处理是怎么回事?
【发布时间】:2017-07-18 16:31:06
【问题描述】:

在大多数平台上,alloca 归结为堆栈指针的内联调整(例如,在 x64 上从 rsp 中减去,加上一些逻辑来保持堆栈对齐)。

我正在查看gcc 为 alloca 生成的代码,这很奇怪。举个简单的例子1

#include <alloca.h>
#include <stddef.h>

volatile void *psink;

void func(size_t x) {
  psink = alloca(x);
}

这将编译为-O2 处的以下程序集:

func(unsigned long):
        push    rbp
        add     rdi, 30
        and     rdi, -16
        mov     rbp, rsp
        sub     rsp, rdi
        lea     rax, [rsp+15]
        and     rax, -16
        mov     QWORD PTR psink[rip], rax
        leave
        ret

这里有几件令人困惑的事情。我知道gcc 需要将分配的大小四舍五入到 16 的倍数(以保持堆栈对齐),通常的方法是 (size + 15) &amp; ~0xF 但它在add rdi, 30 处添加 30?这是怎么回事?

其次,我只希望alloca 的结果是新的rsp 值,它已经很好地对齐了。相反,gcc 这样做:

    lea     rax, [rsp+15]
    and     rax, -16

这似乎是在“重新对齐”rsp 的值以用作 alloca 的结果 - 但我们已经完成了将 rsp 对齐到 16 字节边界的工作。

这是怎么回事?

您可以使用代码on godbolt。值得注意的是,clangicc 至少在 x86 上做了“预期的事情”。使用 VLA(如之前的 cmets 中所建议的),gccclang 可以正常工作,而 icc 会产生可恶的情况。


1 这里,psink 的赋值只是消耗alloca 的结果,否则编译器会完全忽略它。

【问题讨论】:

标签: c gcc x86 alloca


【解决方案1】:

这是一个非常古老的普通优先级bug。代码正常工作。只是当大小大于 1 个字节时,不必要地分配了 16 个字节。所以这不是一个正确性错误,而是一个小的效率错误。

【讨论】:

    猜你喜欢
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 2017-10-20
    • 2013-07-06
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多