关于数据对齐(About Data Alignment)

很多CPU,如基于Alpha,IA-64,MIPS,和SuperH体系的,拒绝读取未对齐数据。当一个程序要求其中之一的CPU读取未对齐数据时,这时CPU会进入异常处理状态并且通知程序不能继续执行。举个例子,在ARM,MIPS,和SH硬件平台上,当操作系统被要求存取一个未对齐数据时默认通知应用程序一个异常。

对齐性
对齐性是一种内存地址的特性,表现为内存地址模上2的幂。例如,内存地址0x0001103F模4结果为3;这个地址就叫做与4n+3对齐,4指出了所选用的2的幂的值。内存地址的对齐性取决于所选择的关于2的幂值。同样的地址模8结果为7。

一个内存地址符合表达式Xn+0,那么就说该地址对齐于X。

CPU执行指令就是对存储于内存上的数据进行操作,这些数据在内存上是以地址为标记的。对于地址来说,单独的数据会有其占用内存的字节数。如果它的地址对齐于它的字节数,那么就称作该数据自然对齐,否则称为未对齐。例如,一个标记8字节的浮点数据的地址对齐于8,那么这个数据就自然对齐。

数据对齐性的编译处理
设备编译器以一种防止造成数据未对齐的方式来对数据进行地址分配。

对于单个的数据类型,编译器为其分配的地址是数据类型字节数的倍数。因此,编译器分配给long型变量的地址为4的倍数,就是说以2进制表示地址的话,最后两位为0。

另外,编译器以一种自然对齐每个结构成员的方式来填充结构体。参看下面的代码里面的结构体struct x_

struct x_
{
char a; // 1 byte
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
} MyStruct;


编译器填充这个结构以使其自然对齐。

例如
下面的代码说明了编译器是如何在内存中填充的。

// Shows the actual memory layout
struct x_
{
char a; // 1 byte
char _pad0[3]; // padding to put 'b' on 4-byte boundary
int b; // 4 bytes
short c; // 2 bytes
char d; // 1 byte
char _pad1[1]; // padding to make sizeof(x_) multiple of 4
}


两种定义在作sizeof(struct x_)运算都会返回12字节。

第二种定义含有两种填充成分:

*char _pad0[3]使得int b在4字节边界上对齐

*char _pad1[1]使得结构数组struct _x bar[3]对齐。
填充使得bar[3]各个变量能够自然对齐。

下面的代码显示了bar[3]的内存结构:


















































































adr offsetelement
------------------
0x0000char a;    // bar[0]
0x0001char pad0[3];
0x0004int b;
0x0008short c;
0x000achar d;
0x000bchar _pad1[1];
0x000cchar a;    // bar[1]
0x000dchar _pad0[3];
0x0010int b;
0x0014short c;
0x0016char d;
0x0017char _pad1[1];
0x0018char a;    // bar[2]
0x0019char _pad0[3];
0x001cint b;
0x0020short c;
0x0022char d;
0x0023char _pad1[1];


没有评论:

发表评论