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

标签 c++ code-generation calling-convention abi stack-allocation

考虑以下示例:

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

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

vector::empty 生成的汇编代码(通过叮当,经过优化):
push    rax
call    vector::size() const
test    eax, eax
sete    al
pop     rcx
ret

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

最佳答案

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

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

  • MSVC : documentation说堆栈总是 16 字节对齐。否 command line argument可以改变这一点。 Godbolt 示例显示,从 rsp 中减去了 40 个字节。在函数的开头,这意味着其他东西也会影响它。
  • 叮当 : -mstack-alignment 选项指定堆栈对齐。似乎默认值是 16,尽管没有记录。如果将其设置为 8,堆栈分配( pushpop )将从生成的汇编代码中消失。
  • gcc : -mpreferred-stack-boundary 选项指定堆栈对齐。如果给定的值为 N,则表示 2^N 字节对齐。默认值为 4,即 16 个字节。如果将其设置为 3(即 8 个字节),堆栈分配( subadd 用于 rsp )将从生成的汇编代码中消失。

  • 查看 godbolt .

    关于c++ - 为什么不使用时分配堆栈内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59636935/

    相关文章:

    c++ - 函数类型语法

    c++ - 方法在类中的位置

    c - 传递给函数的变量是否存储在连续的内存位置?

    c - C 编译器如何在 ASM 中处理函数的结构返回值

    C++ sqlite3 绑定(bind)参数

    javascript - 为什么 Babel.js 将生成器转换为非顺序开关盒?

    javascript - 为什么 .replace() 不处理从 escodege.generate() 生成的大字符串?

    code-generation - 生成代码时,应该生成什么语言?

    c++ - 函数参数在 64 位操作系统的寄存器中传输?

    c++ - 在 windows 中通过 libcurl 通过 ssl 传输 ftp