EXC_ARM_DA_ALIGN问题
同事在做iOS的release版本时出现了一个EXC_ARM_DA_ALIGN的问题,原因是ARM要求内存4字节对齐。
参考以下几个网页梳理来龙去脉如下:
(1)https://brewx.qualcomm.com/bws/content/gi/common/appseng/en/knowledgebase/docs/kb95.html
(2)http://blog.csdn.net/slay_cn/article/details/6221637
(3)http://www.cocos2d-x.org/boards/6/topics/18183?r=22190
按照(1)的说法,这个问题常见于对一个字节流进行处理解析,比如从网络收到一个数据包,读入本地缓存后进行处理,头两个字节是一个short标志,接下来四个字节是一个int参数,所以将指向这个位置的指针直接cast成int*来读取数据——于是问题就出现了,当读int*时,ARM要求字节对齐,而此时不对齐。则有可能出现EXC_ARM_DA_ALIGN异常而崩溃。
治本的解决方法是设计的时候就让数据对齐,可是数据有时候也不是我们设计的,这时候有两种解决方案。
方案1是在指针定义时加上编译器指令PACKED,则编译器在遇到此关键字时就不再要求字节对齐,而是自行进行正确的处理。
方案2是使用memcpy逐字节拷贝来绕过直接的int*指针读取。
在我们的项目中,事实上引擎作者已经使用了方案2的做法来进行处理。那么为什么还有问题呢?按照(2)的说法,是因为memcpy被优化掉了,在优化的版本中,将指针转成long型,4个4个字节的进行复制,于是又出现了字节对齐的问题。解决方案是另写一个低效的memcpy原始版本代替。
再进一步搜索,发现(3)中提到,引擎作者已经发现了这个问题并加以更新,他们的解决方案仍然是使用系统自带的memcpy,但是在传入参数时,先将参数转成void*类型。根据注释来看,如果传入的参数是特定类型,则编译器会自动采用前面说到的优化版本,但是如果传入void*,那么编译器就会采用通用版本,从而避免了问题的出现。
这个问题到此告一段落,但是比较困惑的问题是,这个问题并不是时刻出现的,debug不出现而release出现这可以理解。可在我们的项目里,之前一直没有出错,突然有一天就出错了,同时另一个同事机器上同样的代码就没有出错。。。。。。
另外以前做另一个iPad项目时,有遇到过3D模型从3D Max导出时一定要选择字节对齐,否则一烧到真机运行必定crash,还是必定crash好解决啊~~