为什么分配的变量地址之间相差 16 个字节?
Why there is difference by 16 byte between allocated variables' addresses?
为什么有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 字节的对齐方式出乎意料。
相关文章:
- 如何使用 OpenCV 解码在两个 UWP 应用之间发送的图像字节?
- 如何在带有 mbed 的 nucleo f446re 之间通过带有 UARTSerial 类的 USB 发送字节数组?
- 删除字节数组 : Qt 缓冲区之间的空字符 (\x00)
- 如何封装两个容器之间的传输字节
- ATMega328P 和 ESP8266ex 之间的 I2c 通信只能发送 8 个字节,错误?
- 为什么分配的变量地址之间相差 16 个字节?
- 如何在-120到120之间更改int到char(或其他简单保存为一个字节的简单方法)
- 文件名如何在"char"和2字节字符之间工作
- 解释为 4 个字节的两个整数之间的计算范数
- 正确处理字节对齐问题 - 通过UDP在16位嵌入式系统和32位桌面之间
- 32位和64位Linux机器中4字节类型之间的差异
- C++模需要在两个*无*符号字节之间进行减法转换才能工作,为什么
- 在wchar_t和网络字节之间进行转换
- 转换之间的双和字节数组,为传输ZigBee API
- 为什么堆栈上对齐的整数之间有 8 个字节的"0xcc"填充?C++ 32位视窗7
- 在c++和c#之间传递字节数组ByRef会引发AccessViolationException
- 快速计算两个数组之间相等的字节数
- 在 <T>winrt 组件中的 IVector^ 和 C 样式字节数组之间进行转换
- 将16字节和256字节复制到共享内存之间的差异
- 为什么两个malloc之间有一行额外的8字节