gpt4 book ai didi

c++ - 对齐究竟如何影响内存布局和新布局的行为?

转载 作者:行者123 更新时间:2023-11-30 04:52:33 25 4
gpt4 key购买 nike

我们阅读了很多关于对齐及其重要性的文章,例如放置 new 用法,但我想知道 - 它如何准确地改变内存布局?

显然,如果我们这样做

char buffer[10];
std::cout << sizeof buffer;

alignas(int) char buffer[10];
std::cout << sizeof buffer;

我们得到相同的结果,即 10

但是行为不可能完全一样,对吗?怎么区分呢?我试图寻找答案并跑到 godbolt,测试以下代码:

#include <memory>

int main() {
alignas(int) char buffer[10];
new (buffer) int;
}

在 GCC 8.2 下并且没有优化,导致以下汇编:

operator new(unsigned long, void*):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov QWORD PTR [rbp-16], rsi
mov rax, QWORD PTR [rbp-16]
pop rbp
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16
lea rax, [rbp-12]
mov rsi, rax
mov edi, 4
call operator new(unsigned long, void*)
mov eax, 0
leave
ret

让我们通过删除 alignas(int) 部分来稍微更改代码。现在,生成的程序集略有不同:

operator new(unsigned long, void*):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov QWORD PTR [rbp-16], rsi
mov rax, QWORD PTR [rbp-16]
pop rbp
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16
lea rax, [rbp-10]
mov rsi, rax
mov edi, 4
call operator new(unsigned long, void*)
mov eax, 0
leave
ret

值得注意的是,它仅在 lea 指令上有所不同,其中第二个参数是 [rbp-10] 而不是 [rbp-12] ,正如我们在 alignas(int) 版本中所做的那样。

请注意,我通常不懂汇编。我不会写汇编,但我能读懂它。据我了解,差异只是改变了内存地址的偏移量,这将保存我们的位置-newed int

但是它实现了什么?为什么我们需要那个?假设我们有一个 buffer 数组的“通用”表示,如下所示:

[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]

现在,我假设,在放置 newint(有或没有对齐)之后,我们最终会像这样:

[x] [x] [x] [x] [ ] [ ] [ ] [ ] [ ] [ ]

其中 x 表示 int 的单个字节(我们假设 sizeof(int) == 4)。

但我一定遗漏了什么。还有更多,我不知道是什么。通过将 buffer 对齐到 int 合适的对齐方式,我们究竟实现了什么?如果我们这样对齐会怎样?

最佳答案

在某些架构上,类型必须对齐才能使操作正常进行。例如,int 的地址可能需要是 4 的倍数。如果它不是这样对齐的,那么对内存中的整数进行操作的 CPU 指令将无法工作。

即使当数据没有很好地对齐时一切工作,对齐对于性能仍然很重要,因为它确保整数等不会跨越缓存边界。

当您将 char 缓冲区与整数边界对齐时,它不会影响 placement new 的工作方式。它只是确保您可以使用 placement new 将 int 放在缓冲区的开头,而不会违反任何对齐约束。它通过确保缓冲区的地址是 4 字节的倍数来实现这一点。

关于c++ - 对齐究竟如何影响内存布局和新布局的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54337626/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com