为什么栈内存在不用的时候分配?
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?它根本没有被使用。 push
和 pop
可以省略。 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,堆栈分配(push
和 pop
)将从生成的汇编代码中消失。
- gcc:
-mpreferred-stack-boundary
选项指定堆栈对齐方式。如果给定的值为 N,则表示对齐 2^N 个字节。默认值为 4,即 16 个字节。如果将其设置为 3(即 8 个字节),堆栈分配(sub
和 add
for rsp
)将从生成的汇编代码中消失。
查看 godbolt。
考虑以下示例:
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?它根本没有被使用。 push
和 pop
可以省略。 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,堆栈分配(push
和pop
)将从生成的汇编代码中消失。 - gcc:
-mpreferred-stack-boundary
选项指定堆栈对齐方式。如果给定的值为 N,则表示对齐 2^N 个字节。默认值为 4,即 16 个字节。如果将其设置为 3(即 8 个字节),堆栈分配(sub
和add
forrsp
)将从生成的汇编代码中消失。
查看 godbolt。