为什么不使用时分配堆栈内存?

Dr.*_*Gut 14 c++ code-generation abi calling-convention stack-allocation

考虑以下示例:

struct vector {
    int  size() const;
    bool empty() const;
};

bool vector::empty() const
{
    return size() == 0;
}
Run Code Online (Sandbox Code Playgroud)

生成的汇编代码vector::empty(通过 clang,经过优化):

push    rax
call    vector::size() const
test    eax, eax
sete    al
pop     rcx
ret
Run Code Online (Sandbox Code Playgroud)

为什么要分配堆栈空间?它根本没有被使用。该pushpop可以省略。MSVC 和 gcc 的优化构建也为此功能使用堆栈空间(请参阅有关Godbolt 的内容),因此必须有一个原因。

gez*_*eza 11

它分配堆栈空间,因此堆栈是 16 字节对齐的。它是必需的,因为返回地址需要 8 个字节,因此需要额外的 8 个字节空间来保持堆栈 16 字节对齐。

对于某些编译器,可以使用命令行参数配置堆栈帧的对齐方式。

  • MSVC文档说堆栈总是 16 字节对齐。没有命令行参数可以改变这一点。Godbolt 示例显示,从rsp函数的开头减去了 40 个字节,这意味着其他因素也会对此产生影响。
  • clang:该-mstack-alignment选项指定堆栈对齐。似乎默认值是 16,尽管没有记录。如果将其设置为 8,堆栈分配(pushpop)将从生成的汇编代码中消失。
  • gcc:该-mpreferred-stack-boundary选项指定堆栈对齐方式。如果给定的值为 N,则表示 2^N 字节对齐。默认值为 4,即 16 个字节。如果将其设置为 3(即 8 个字节),则堆栈分配(subaddfor rsp)将从生成的汇编代码中消失。

Godbolt查看

  • @Dr.Gut:谢谢,您使答案变得更好和完整。请注意,堆栈对齐通常记录在系统的 ABI 中(例如,对于某些系统,以下是文档:https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI)。 (2认同)