IOS-内存对齐

混江龙づ霸主 提交于 2019-12-30 20:18:15

一. 内存对齐是什么?

在计算机中,内存大小的基本单位是字节,理论上来讲,可以从任意地址访问某种基本数据类型。

但是实际上,计算机并非按照字节大小读写内存,而是以2、4、8的倍数的字节块来读写内存。因此,编译器会对基本数据类型的合法地址作出一些限制,即它的地址必须是2、4、8的倍数。那么就要求各种数据类型按照一定的规则在空间上排列,这就是对齐。

在iOS开发过程中,编译器会自动的进行字节对齐的处理,并且在64位架构下,是以8字节进行内存对齐的。

二、内存对齐的原则

内存对齐应该是编译器的管辖范围,编译器为程序中的每个数据单元安排在适当的位置上,方便计算机快速高效的进行读取数据。
每个平台的编译器都有自己的对齐系数和相应的对齐规则。在iOS中的64位架构下,对齐系数就是8个字节。

三. 数据成员对齐

结构体或者共用体中的成员变量中,首个成员变量放在偏移量为0的位置上,后面的成员变量的对齐偏移量是取指定对齐系数和本身该成员变量所占用大小中的较小值,即min(对齐系数,成员变量的内存大小 )

四. 数据整体对齐

在结构体或者共用体中的成员变量完成自身的对齐之后,整个结构体或者共用体也需要进行字节对齐处理,一般为min(对齐系数,最大成员变量的内存大小 )的整数倍。

结合上述原则1、2,可以推断出下面的常用原则,以结构体为例:

  • 结构体变量的首地址是其最长基本类型成员的整数倍;
  • 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如不满足,对前一个成员填充字节以满足;
  • 结构体的总大小为结构体最大基本类型成员变量大小的整数倍;
  • 结构体中的成员变量都是分配在连续的内存空间中。

四. 内存对齐的原因

1.为了减少CPU访问内存的次数,提高计算机性能,一些计算机硬件平台要求存储在内存中的变量按自然边界对齐。
性能上的提升

从内存占用的角度讲,对齐后比未对齐有些情况反而增加了内存分配的开支,是为了什么呢?
数据结构(尤其是栈)应该尽可能地在自然边界上对齐,为了访问未对齐的内存,处理器(CPU)需要作两次内存访问;而对齐的内存访问仅需要一次访问。最重要的是提高内存系统的性能。

跨平台

有些硬件平台并不能访问任意地址上的任意数据的,只能处理特定类型的数据,否则会导致硬件层级的错误。

有些CPU(如基于 Alpha,IA-64,MIPS,和 SuperH 体系的)拒绝读取未对齐数据。当一个程序要求这些 CPU 读取未对齐数据时,这时 CPU 会进入异常处理状态并且通知程序不能继续执行。

举个例子,在 ARM,MIPS,和 SH 硬件平台上,当操作系统被要求存取一个未对齐数据时会默认给应用程序抛出硬件异常。所以,如果编译器不进行内存对齐,那在很多平台的上的开发将难以进行。

内存对齐的注意事项

在结构体中,声明成员变量的顺序不一致,也会导致最终分配内存大小的不同。

4.1 内存分配

4.2 跨平台通信
在跨平台通信的过程中,由于不同平台的对齐方式或者对齐系数可能不同,这样就会导致同样的数据结构在不同的平台其内存大小就可能存在不同。

总结

在真正的开发过程中,我们不用过多关注字节对齐的问题,编译器会帮我们处理好。但是,我们能做的是,在设计数据结构时,合理安排成员变量的顺序。具体总结如下:

  • 跨平台数据结构可考虑1字节对齐,节省空间但影响访问效率;
  • 结构体成员合理安排位置,以节省空间;
  • 跨平台数据结构人为进行字节填充,提高访问效率但不节省空间;
  • 本地数据采用默认对齐,以提高访问效率;
  • 在32位或者64位架构下,默认对齐系数是不一样的。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!