我们读了很多关于对齐和它有多重要的内容,例如放置
new
用法,但我想知道-它如何准确地改变内存的布局?
显然,如果我们这样做的话
char buffer[10];
std::cout << sizeof buffer;
和
alignas(int) char buffer[10];
std::cout << sizeof buffer;
我们得到同样的结果,也就是
10
.
但行为不能完全相同,是吗?为什么它是可区分的?我试图寻找答案,然后跑向戈德博尔特,测试以下代码:
#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]
就像我们在
对齐(int)
版本。
请注意,我一般不理解装配。我不能写汇编,但我能读一些。据我所知,差异只是改变了内存加法器的偏移量,这将保持我们的位置。-
新的
预计起飞时间
int
.
但是它实现了什么呢?为什么我们需要那个?假设我们有一个
buffer
数组如下:
[ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
现在,我想,在安置之后-
新的
ing
int
(
有无
我们最终会得到这样的结果:
[x] [x] [x] [x] [ ] [ ] [ ] [ ] [ ] [ ]
哪里
x
表示
int
(我们假设
sizeof(int) == 4
)
但我一定错过了什么。还有很多,我不知道是什么。我们通过调整
缓冲区
到
int
适合对齐?如果我们
不要
对齐它吗?