某一款ARM设备界面程序开发: 为避免通讯过程中重复申请内存增加内存碎片率并影响效率,开始申请足够大小空间作为内存池供通讯数据使用,根据界面程序收到通讯数据大小在内存池中找到未被利用的内存块,使用完毕之后释放,归还至内存池。
1. 收到通讯数据并转化为字节对齐结构,转化成功,但是在获取该结构中具体值时偶尔会出现程序奔溃情况(会报BUS Err错误),
2. 将该段内存数据转化为char*并打印出来,发现该段内存中所存数据有效;
3. 放弃强制类型转换, 采用strncpy函数,将该结构大小数据复制出来,并获取具体值,程序未出现奔溃情况,并且所获取值正确。
4. 查看Bus Error 错误原因,可能是字节未对齐,查看结构,已经4字节对齐;打印出该结构存储起始地址,发现未奔溃情况下地址均为:7516D008 ,而地址为7516D00A时,程序偶尔会奔溃。
5. 查看字节对齐介绍:如果该结构n字节对齐,则存放该结构的内存起始地址是n的整数倍,如果不是n的整数倍,则在精简指令CPU等机器(ARM)中会出现BUS ERR 问题,而在X86中不会出现错误。 结合第四步程序奔溃时结构起始地址7516D00A并不是4的整数倍
6. 初步确定是结构未4字节对齐引发内存池中分配起始地址未能是4的整数倍而出现BUS ERR ,查看所有通讯数据,发现在某一过程出现2字节对齐结构(内存池起始地址:0x0000,分配2字节后,内存池起始地址为:0x0002,然后2字节未释放的情况下分配4字节对齐结构内存,则起始地址为:0x0002,显然不是4的整数倍,则在ARM中会出现BUS ERR错误)
总结: 在自定义内存池并管理内存池时,要特别注意字节的对齐问题,如果该结构N字节对齐,则保证每次分配的内存块起始地址为N的整数倍,
特别说明:
在Linux下: BUS ERROR(SIGBUS) 一般是字节未对齐出错
SIGSEGV 一般是内存地址不合法造成的
在精简指令CPU下,内存分配起始地址必须是结构N字节对齐的整数倍数,也就是说n字节对齐的结构,存储该结构的内存起始地址必须是n的整数倍数, 在X86上不会报错,但是会影响效率。
我自己在项目中遇到的问题,希望对同行有所帮助.................................