内存对齐机制

来源:互联网 发布:仿创业邦网站源码 编辑:程序博客网 时间:2024/05/28 06:04

我相信在网上已经有很多关于内存对齐机制的文章了,在这里,我只想通过一个小例子来阐明内存分配的现象

有这样的一段代码:

//: 内存对齐_2#include <cstdio>struct A {  char   m1;  // 1  double m2;  // 8  int    m3;  // 4};int main() {  A a = {'A', 0.2, 4};  printf("sizeof(A) = %d\n", sizeof(A));  printf("A.m1      = %ld\n", long(&a.m1));  printf("A.m2      = %ld\n", long(&a.m2));  printf("A.m3      = %ld\n", long(&a.m3));  printf("-----------------\n\n");  return 0;} ///:~ 


至于地址为什么是递增的就不多做解释了(编译器压入栈的顺序有关),在 VC 6.0 下进行调试,为了了解 a.m1、a.m2、a.m3 在内存中的对齐情况,先找出 a.m1 的内存地址:


这里的 0x0012ff30 就是 a.m1 的内存地址了,再来看 a.m1、a.m2、a.m3 的内存对齐情况:


图中正是 0x0012ff30 内存布局情况,其中红色框子分别表示 a.m1、a.m2、a.m3(在 32 位机上面,char 占 1 个字节,int 占 4 个字节,double 占 8 个字节,1 字节 = 8 位,每 4 位以 16 进制形式表示),浅蓝色框子表示填充部分(padding):

在 0x0012ff30 地址先存放了 char 类型的 m1,占 1 个字节(2 位),接着就要存放 double 类型的 m2,因为 m2 需要占 8 个字节(在内存对齐机制中,为了减少处理器对内存的访问次数,通常编译器都会在编译阶段对齐字节,规则是变量的内存地址必须是该变量字节数的整数倍),因此,存放完 m1 以后还要填充 7 个字节长度的内存,这样 m1 总的大小就占了 8 个字节长度;存放完 m2 以后,m3 占 4 个字节,前两者共占了 16 个字节,m3 的内存地址满足其字节倍,是不是就不需要填充呢?

如图示,答案就在图上,不是的,考虑定义结构体数组 A a[] = {0}; 编译器为了确保处理器总是一次就可以访问完一个变量,在分配内存的时候以结构体中“字节数最大的”变量进行分配,也就是满足 address + 8n;

尽管看来编译器花费了更多的内存去完成这件工作,但是对于整体的效率来说,却是获益了不少


不错的参考资料:

1. 《深入理解计算机系统》 Chapter 3 程序的机器级表示 3.9.3

2. 百度百科 http://baike.baidu.cn/view/4786260.htm

3. 内存对齐的原理,作用……  http://lc7cl.iteye.com/blog/1250481

4. C/C++内存分配与内存对齐全面探讨(比较详细,没看完)  http://blog.csdn.net/cuibo1123/article/details/2547442

5. 一篇讲对齐比较好的文章  http://old.uplook.cn/blog/10/109320/

6. C++内存对齐详细使用指南(不建议一开始看) http://developer.51cto.com/art/201002/183652.htm


原创粉丝点击