为什么栈内存在不用的时候分配?

Why is stack memory allocated when it is not used?

考虑以下示例:

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

bool vector::empty() const
{
    return size() == 0;
}

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

push    rax
call    vector::size() const
test    eax, eax
sete    al
pop     rcx
ret

为什么分配栈space?它根本没有被使用。 pushpop 可以省略。 MSVC 和 gcc 的优化构建也为此函数使用堆栈 space(参见 godbolt),所以一定是有原因的。

它分配栈space,所以栈是16字节对齐的。这是必需的,因为 return 地址占用 8 个字节,所以需要额外的 8 个字节 space 来保持堆栈 16 字节对齐。

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

  • MSVC: documentation says that the stack is always 16-byte aligned. No command line argument 可以改变这个。 godbolt 示例显示函数开头的 rsp 减去 40 个字节,这意味着其他因素也会影响此。
  • clang-mstack-alignment选项指定堆栈对齐方式。看起来,默认值是 16,虽然没有记录。如果将其设置为 8,堆栈分配(pushpop)将从生成的汇编代码中消失。
  • gcc-mpreferred-stack-boundary选项指定堆栈对齐方式。如果给定的值为 N,则表示对齐 2^N 个字节。默认值为 4,即 16 个字节。如果将其设置为 3(即 8 个字节),堆栈分配(subadd for rsp)将从生成的汇编代码中消失。

查看 godbolt