数据对齐问题

来源:互联网 发布:php支付宝服务端demo 编辑:程序博客网 时间:2024/06/08 06:10

数据对齐(data alignment)在编程中是一个很常见的问题。以前,对这个问题总是似懂非懂,遂决定彻底弄清楚其中缘由。在看了一些参考文献后,算是对这个问题有了一个大致的了解,这里做一个简单的总结。

数据对齐,简单地说是指让数据的起始内存地址为2的k次幂(k=0,1,2,3,4,....)字节;从另一个方面来讲,我们说一个数据对齐到X是指,其地址是可以表示为n*X+0的形式。数据对齐的目的在于提升程序运行的速度,减少内存读取的次数。大多数CPU,如IA-32(64)、MIPS等都需要对数据进行对齐处理,若遇到未对齐的数据,就会产生一个异常,叫 unaligned access,并迫使程序终止。在编写程序的过程中,若未能对数据进行对齐处理,有可能会出现以下几个问题(具体见:Data alignment: Straighten up and fly right):

  • 程序运行变慢;
  • 应用程序可能会出现死锁;
  • 操作系统可能会崩溃;
  • 程序意外终止,输出不正常的结果。
那么如何对数据进行对齐处理?通常的建议是,对于那些本身大于16 bytes的数据最好将其对齐至16-byte的地址。一般而言,为了实现更好的性能,可以遵循以下几个准则:
  • 8-bit(char类型)的数据可以对齐到任意地址(2字节);
  • 16-bit(int类型,long类型,float类型)的数据需要对齐到4-byte地址(2字节);
  • 32-bit(double类型)的数据的起始地址在Windows环境下进行8-byte对齐处理,而在Linux环境下进行4-byte对齐处理(也可以选择8-byte对齐);
  • 64-bit(long long类型)的数据的起始地址为8-byte的整数倍;
  • 80-bit的数据的起始地址为16-byte的整数倍;
  • 128-bit的数据的起始地址为16-byte的整数倍;
  • 对于任何指针型变量,都对齐到4-byte地址;
很多公司在笔试面试过程中,喜欢出一类数据对齐问题:结构体变量的数据对齐问题(data structure alignment)。这类问题一般可以分两个步骤来解决:
  1. 按照上述规则,对结构体变量中的各个数据变量进行对齐处理;
  2. 对整个结构体变量进行数据对齐处理,保证结构体变量的大小为其中最大变量大小的整数倍;
考虑以下这个结构体变量_x:
struct _x{   char a;     // 1 byte   int b;      // 4 bytes   short c;    // 2 bytes   char d;     // 1 byte} MyStruct;
可以这样来计算_x的大小:
  1. 对各个变量进行对齐处理。对于字符变量a而言,由于它可能对齐到任意地址,所以无须做处理;对int型变量b,由于需要确保其起始地址为4-byte的整数倍,而未对齐处理之前其起始地址为1-byte的整数倍,因此需要在变量a之后进行数据的填充(加入3 个字符变量内存)。在对齐变量b后,short型变量的内存地址为2-byte的整数倍,满足数据对齐的要求,因而不需要做任何处理。字符变量d与字符变量a一样,可以对齐到任意地址。
  2. 对整个结构体变量进行对齐处理,确保sizeof(_x)=sizeof(b)*n(n=1,2,3,...)。在对各个变量进行对齐之后,4个变量占有的内存大小为1+3+4+2+1=11 bytes,为使sizeof(_x)的大小为sizeof(b)的整数倍,需要在变量d后进行数据填充处理(加入1个字符变量的内存),从而sizeof(_x)=12 bytes,为4-byte的整数倍。
其他类型的数据对齐问题同样可以按照上述的方法进行计算处理,有关数据处理更深层次的问题可以参考:Data alignment: Straighten up and fly right

参考文献:
[1] data alignment when migrating to 64-bit intel architecture
[2] Data structure alignment
[3] About data alignment
[4] Data alignment: Straighten up and fly right
[5] Byte Alignment And Ordering
[6] purpose of memory alignment

原创粉丝点击