[复习]内存对齐
1. 概念:程序员眼中的内存是按byte存储的;而cpu眼中的内存是以chunk为单位的,chunk可以是2,4,8bytes。如果放在内存中的数据没有被对齐即其内存地址不是对应cpu内存访问粒度的整数倍,读取这段数据cpu就需要更多次的内存访问,相比较对齐的内存数据而言。内存对齐后,占据的内存必然是增多的。
2. 最明显的获知有内存对齐这回事的例子是sizeof(struct a)。由于我们可以通过编译选项#pragma pack(n)来控制数据的内存存放的对齐粒度(1,2,4,8),从而可以很容易测试得到在不同的对齐粒度下,同一个struct变量占据的内存大小的变化。
3. 编译器根据内存对齐粒度是如何进行对齐的呢?看百度百科中的例子:http://baike.baidu.com/view/4786260.html
4. 针对字节对齐,我们在编程中如何考虑? 如果在编程的时候要考虑节约空间的话,那么我们只需要假定结构的首地址是0,然后各个变量按照上面的原则进行排列即可,基本的原则就是把结构中的变量按照类型大小从小到大声明,尽量减少中间的填补空间.
5. 另外一个概念是system granularity,可以由GetSystemInfo获得。它的含义是:系统为一个进程分配空间的分配粒度,一般应该是64KB。Windows 将保留的进程地址空间中的每个区域对齐成从一个“整”(二进制的整数)的边界。这个边界由系统的分配粒度(allocation granularity)值定义。通过Windows的 GetSystemInfo 函数,可获得此分配粒度值。当地址空间的一个区域被保留时,Windows确保该区域的大小和基址总是系统页面大小的整数倍。如X86系统使用4KB的页面,如果试图保留一个 18KB大小的区域,系统将保留20KB,如果指定了这个18KB区域的基址为3KB,则实际被保留的数量是24KB。
6. 内存对齐的原因
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
2. 最明显的获知有内存对齐这回事的例子是sizeof(struct a)。由于我们可以通过编译选项#pragma pack(n)来控制数据的内存存放的对齐粒度(1,2,4,8),从而可以很容易测试得到在不同的对齐粒度下,同一个struct变量占据的内存大小的变化。
3. 编译器根据内存对齐粒度是如何进行对齐的呢?看百度百科中的例子:http://baike.baidu.com/view/4786260.html
4. 针对字节对齐,我们在编程中如何考虑? 如果在编程的时候要考虑节约空间的话,那么我们只需要假定结构的首地址是0,然后各个变量按照上面的原则进行排列即可,基本的原则就是把结构中的变量按照类型大小从小到大声明,尽量减少中间的填补空间.
5. 另外一个概念是system granularity,可以由GetSystemInfo获得。它的含义是:系统为一个进程分配空间的分配粒度,一般应该是64KB。Windows 将保留的进程地址空间中的每个区域对齐成从一个“整”(二进制的整数)的边界。这个边界由系统的分配粒度(allocation granularity)值定义。通过Windows的 GetSystemInfo 函数,可获得此分配粒度值。当地址空间的一个区域被保留时,Windows确保该区域的大小和基址总是系统页面大小的整数倍。如X86系统使用4KB的页面,如果试图保留一个 18KB大小的区域,系统将保留20KB,如果指定了这个18KB区域的基址为3KB,则实际被保留的数量是24KB。
6. 内存对齐的原因
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
参考:
http://blog.ednchina.com/colinluan/159417/message.aspx
http://www.cnblogs.com/xingluzhe/archive/2009/09/01/1557866.html