为什么分配的变量地址之间相差 16 个字节?

Why there is difference by 16 byte between allocated variables' addresses?

本文关键字:字节 之间 分配 变量 地址 为什么      更新时间:2023-10-16

为什么有8个字节(在64位系统上为16个)?这种对齐的原因是什么?

例:

int* ptr1 = new int;
int* ptr2 = new int;
int* ptr3 = new int;
cout << ptr1 << " " << ptr2 << " " << ptr3 << endl;
cout << ptr2 - ptr1 << endl;

输出:

0x15cbc20 0x15cbc40 0x15cbc60  
8
int* ptr1 = new int;
int* ptr2 = new int;
int* ptr3 = new int;

首先,不能保证这些语句将分配有关sizeof(int)的连续内存地址。

这种对齐的原因是什么?

因为 CPU 具有用于访问堆分配数据的缓存,并且这些缓存经过优化,可对 32 位或 64 位指针使用字节对齐访问,具体取决于目标体系结构。

实际上有两件事通常是负责的:

  • 对齐(其他答案涉及此)
  • 簿记信息

例如,当您请求 4 个字节的内存时,您的底层内存分配器(所选operator new(...)使用的任何内存分配器)可能会使用一些额外的字节来存储一些簿记信息。在这里看到一个很好的解释

簿记信息通常是delete工作的原因,而不必告诉它请求的原始内存大小。

例如:

void* Malloc(std::size_t size){
//Allocator searches for free memory
auto FreeList = GetNextFreeNodeOfAtLeast(size + 16);
//Rounds the requested size to the ceil of CPU word size
size = RoundToWordAlignment(size);
//Allocate with an extra 16 bytes for bookkeeping
void* Memory = FreeList->Allocate(size + 16);
//Use the Upper 16bytes... some implementations use lower..
auto info = static_cast<MallocInformation*>(Memory + size);
//Create an Info object so that `Free` or operator delete can use to free memory
new(info) MallocInformation(size, FreeList, ....);
//Return the Memory
return Memory;
}

分配给您的每个内存都附加了一些积压的信息。内存分配器有许多不同的工作方式,有些具有指向管理内存的某个主结构的单个指针的簿记信息。

C++标准不要求连续的内存分配是连续的,也没有指定它们之间的内存"间隙"大小。

不能保证动态分配的对象将相邻存储(即使在相邻的对齐地址中)。您的分配器碰巧将内存8*sizeof(int)(在您的系统上为 32 个)字节分开,这是一个实现细节。

operator new通常是使用malloc实现的(尽管不能保证,这是另一个实现细节)。使用malloc分配内存时,无法请求特定的对齐。这就是为什么保证为任何内置类型分配适当对齐的内存,即sizeof(maxalign_t)边界。因此,对于典型的实现,我不会发现 8 或 16 字节的对齐方式出乎意料。