美文网首页
内存对齐

内存对齐

作者: 夜空中乄最亮的星 | 来源:发表于2023-01-28 18:42 被阅读0次

    概念

    对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐。比如在32cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的。

    为什么要字节对齐

    • CPU每次寻址都是要消费时间的,并且CPU访问内存时,并不是逐个字节访问,而是以字长(word size)为单位访问,所以数据结构应该尽可能地在自然边界上对齐,如果访问未对齐的内存,处理器需要做两次内存访问,而对齐的内存访问仅需要一次访问,内存对齐后可以提升性能
    • 有些CPU可以访问任意地址上的任意数据,而有些CPU只能在特定地址访问数据,因此不同硬件平台具有差异性,这样的代码就不具有移植性,如果在编译时,将分配的内存进行对齐,这就具有平台可以移植性了

    如何进行对齐?

    • 基本数据类型:地址只要是它的长度的整数倍即可
    • 数组:按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了
    • 联合:按其包含的长度最大的数据类型对齐
    • 结构体:结构体中每个数据类型都要对齐

    对齐数

    对齐数 =编译器默认值成员自身大小 两者的较小值
    32位cpu上默认的指定对齐值是4字节,64位cpu上默认的指定对齐值是8字节

    对齐规则

    1. 第一个成员一定对齐,位于结构体变量偏移量(offset)为0的地址处。
    2. 其他成员要对齐到对齐数的整数倍的地址处(当前起始偏移量 % min(成员大小, 对齐数) == 0)
    3. 结构体 总大小必须为最大对齐数(每个成员都有一个对齐数)的整数倍。
    4. 如果嵌套了结构体的情况,先按规则计算出嵌套的结构体大小,最后结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

    举例(golang)

    // 64位平台,对齐参数是8
    type User struct {
     A int32 // 4
     B []int32 // 24 ,切片结构体中每个成员占用8字节
     C string // 16 ,字符串结构体类型占用16字节
     D bool // 1
    }
    

    对齐参数是8,int32、[]int32、string、bool对齐值分别是4、8、8、1,占用内存大小分别是4、24、16、1,我们先根据第一条对齐规则分析User:

    • 第一个字段类型是int32,对齐值是4,大小为4,所以放在内存布局中的第一位.
    • 第二个字段类型是[]int32,对齐值是8,大小为24,按照第一条规则,偏移量应该是成员大小24与对齐值8中较小那个的整数倍,那么偏移量就是8,所以4-7位会由编译进行填充,一般为0值,也称为空洞,第9到32位为第二个字段B.
    • 第三个字段类型是string,对齐值是8,大小为16,所以他的内存偏移值必须是8的倍数,因为user前两个字段就已经排到了第32位,所以offset为32正好是8的倍数,不要填充,从32位到48位是第三个字段C.
    • 第四个字段类型是bool,对齐值是1,大小为1,所以他的内存偏移值必须是1的倍数,因为user前两个字段就已经排到了第48位,所以下一位的偏移量正好是48,正好是字段D的对齐值的倍数,不用填充,可以直接排列到第四个字段,也就是从48到第49位是第三个字段D

    ©著作权归作者所有:来自51CTO博客作者Golang梦工厂的原创作品,请联系作者获取转载授权,否则将追究法律责任
    详解内存对齐
    https://blog.51cto.com/u_14523732/5707302

    相关文章

      网友评论

          本文标题:内存对齐

          本文链接:https://www.haomeiwen.com/subject/ehvehdtx.html