C++ 数据对齐 问题

上一篇文章提到了数据对齐问题,那我们就来看看C++数据对齐的规则,举例分析一下,最后看一个由数据对齐引起的BUG,并思考其带给我们的意义。

首先为什么要数据对齐?现代的64位计算机,总线位宽为64个比特(bit),即8个字节(byte),CPU的寄存器也是8个字节大小,所以访问内存也总是以8个字节为单位。如果一份不足8字节大小的数据因为布局问题跨越了两个8字节单位,这样要读这份数据的时候,就要通过两次总线传输,传递16字节的数据,CPU也要分级缓存这16字节的数据,这实在是太糟糕了。同理,对于32位的系统,小于4字节的数据就不应该夸两个4字节空间,还有其他的平台可能数据访问一次只有2字节甚至1字节。综合这些,数据对齐就是要求数据应该排放在其大小的自然边界上,简单说就是大小为N(1,2,4,8,16,32)的数据不应该放在两个N格子之间,而应该放在一个单独的N格子之内。

上面解释了为什么要数据对齐,要对齐的情况好像还挺多的,也挺复杂的。我们把编译器关于数据对齐的策略总结为三条规则。

规则一:成员变量根据自己的大小来对齐。

规则一的意思就是,关于结构体内该成员是否要对齐,对齐到什么位置,不是看上一个变量,也不是看下一个变量,而是看自己。定义一个int,就要对齐到sizeof(int)整数倍的位置,定义一个double,就要对齐到sizeof(double)整数倍的位置。

规则二:结构体大小必须是最大成员变量大小的整数倍。

规则二定义的是结构体数组最后补齐的情况,如果一个结构体中定义了一个int与一个double,那么最大成员变量是double,大小为8。这时结构体虽然只有4(int) + 8(double)= 12字节大小,但会补齐为8的整数倍 16。这样做是为了处理结构体数组时,每一个结构体内的每一个成员变量都处于边界上。

结合规则一与规则二,我们就可以处理简单结构体的数据对齐了,先来看个例子:

Continue reading