2017-03-05 39 views
3

为什么要对齐到8个字节(在64位系统上是16)?这种对齐的原因是什么?为什么分配的变量地址之间有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 
+0

实际上,看你提供的输出,你分配的整数是32字节。 –

+0

完全取决于使用什么内存分配算法。分配的块不太可能与所请求的类型大小完全匹配,但至少与对齐,或者像默认分配器一样使用最小内存块。 –

+1

对齐完成后,CPU可以更快地从主内存中读取 – stackptr

回答

1

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

  • 对齐(处理了这个其它的答案)
  • 簿记信息

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

记账信息通常是为什么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++标准不要求连续的内存分配是连续的,也不需要指定它们之间有多少内存“间隙”。

+0

CPU字是2个字节,对不对? 因此,这种对齐对于重叠大小来说不是那么重要。或者有一些额外的对齐方式,不仅仅是单词? – Elengar

3
int* ptr1 = new int; 
int* ptr2 = new int; 
int* ptr3 = new int; 

1日没有保证,这些语句将分配有关sizeof(int) contigous内存地址。

这种对齐的原因是什么?

由于CPU具有访问堆分配数据的缓存,并且这些缓存已针对32位或64位指针使用字节对齐访问进行了优化,具体取决于目标架构。

1

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

operator new通常(但不保证,这是另一个实现细节)使用malloc实现。使用malloc分配内存时,无法请求特别对齐。这就是为什么它保证为任何内置类型分配合适对齐的存储器,即分配给sizeof(maxalign_t)边界。因此,对于典型的实现,我不会发现意外的8或16字节的对齐。

相关问题