字节对齐导致的iOS EXC_ARM_DA_ALIGN崩溃
本文原链接: http://www.cnblogs.com/zouzf/p/4455167.html
先看一下这个链接:http://www.cnblogs.com/ren54/archive/2013/01/11/2856207.html
我遇到情况和这位朋友很类似:用二进制方式从文件读取内容到内存,假设内容只有7个字节,前面三个字节是三个字符,后四个字节的内容是一个int数据,在把后四个字节转成int数据时如(pFileContent是char*指针,已指向第四个字节):int intValue = *(pFileContent); 就会崩溃报EXC_ARM_DA_ALIGN错误。
查了一下资料:http://www.justinyan.me/post/1609 、http://www.shaoqun.com/a/54537.aspx 、http://blog.csdn.net/slay_cn/article/details/6221637 ,是因为字节对齐问题引起的,大概描述如下(摘自前面三篇资料):
内存地址空间以byte划分,所以理论上访问内存地址可以从任意byte开始,但是事实上我们不是直接访问硬件地址,而是通过操作系统的虚拟内存地址来访问,虚拟内存地址是以字为单位的。一个32位机器的字长就是32位,所以32位机器一次访问内存大小就是4个byte。再者为了性能考虑,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。 这个问题常见于对字节流进行处理解析,比如从网络收到一个数据包,读入本地缓存后进行处理,头两个字节是一个short标志,接下来四个字节是一个int参数,所以将指向这个位置的指针直接cast成int*来读取数据——于是问题就出现了,当读int*时,ARM要求字节对齐,而此时不对齐。则有可能出现EXC_ARM_DA_ALIGN异常而崩溃。
大概就是说,在进行强制数据类型转换的时候,(release版本)会要求内存字节对齐。编译release版本,编译器会对代码进行优化,在处理数据时要求数据结构在自然边界上对齐以提高CPU效率。
解决方法了http://www.shaoqun.com/a/54537.aspx:
方案1、在指针定义时加上编译器指令PACKED,则编译器在遇到此关键字时就不再要求字节对齐,而是自行进行正确的处理。
方案2、使用memcpy逐字节拷贝来绕过直接的int*指针读取。给memcpy传入参数时,先将参数转成void*类型,因为release的memcpy被优化掉了,在优化的版本中,将指针转成long型,4个4个字节的进行复制,于是又出现了字节对齐的问题。
我采用了方案2,给memcpy传参数时转成 void* 。
后记
当读取文件获取数据时经常会采用反序列化的方式来提高效率,如上篇文章提到的骨骼动画的优化,这个时候要特别注意字节对齐的问题,特别是现在做手游基本都会涉及到多平台,在定义一些struct时最好显示调用
#pragma pack(n)来指定字节对齐。windows下编译器默认是8字节对齐的,mac、iOS、Android(如果有误请指正)默认是4字节对齐的,而经常发生的时,在windows下对文件资源进行序列化,然后在iOS和Android上运行的时候读取文件进行反序列化,如果有个结构体如 struct myTest { char[5] name; int age; };就出问题了,windows下写进文件需要16个字节,而ARM设备下读取文件反序列化需要12个字节~~
上面说到:windows下默认是8字节对齐的,mac、iOS、Android(如果有误请指正)默认是4字节对齐的 ,这个说法是不严谨的,应该更多的是跟编译器有关吧,而编译器会根据系统和CPU特性来决定的吧,这块了解得不多,有了解的朋友可以留下链接和看法,谢了。
另外还有个疑惑,那个EXC_ARM_DA_ALIGN 崩溃会出现在Xcode5.1.1 出的release版本,而Xcode5.0.1 出的release版本却没事,一个小版本的有必要差异那么大么。。。。
本文原链接: http://www.cnblogs.com/zouzf/p/4455167.html
字节对齐导致的iOS EXC_ARM_DA_ALIGN崩溃的更多相关文章
- C语言字节对齐问题详解
引言 考虑下面的结构体定义: typedef struct{ char c1; short s; char c2; int i; }T_FOO; 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始 ...
- C语言字节对齐问题详解(对齐、字节序、网络序等)
首先说明一下,本文是转载自: http://www.cnblogs.com/clover-toeic/p/3853132.html 博客园用的少,不知道怎么发布转载文章,只能暂时这样了. 引言 考虑下 ...
- C语言字节对齐问题详解【转】
引言 转自:http://www.cnblogs.com/clover-toeic/p/3853132.html 考虑下面的结构体定义: 1 typedef struct{ 2 char c1; 3 ...
- [转]C语言字节对齐问题详解
C语言字节对齐问题详解 转载:https://www.cnblogs.com/clover-toeic/p/3853132.html 引言 考虑下面的结构体定义: typedef struct{ ch ...
- arm的字节对齐问题总结(转)
问题由来:pc的lsb总是0,因为代码至少要字对齐.cm3的指令至少是半字对齐的(16) 一.啥是字对齐?为啥要字对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访 ...
- 关于C语言中结构体中的结构体成员导致的字节对齐问题
关于结构体的字节对齐是什么,就不赘述,再此附上一篇文章,介绍字节对齐:http://www.linuxsong.org/2010/09/c-byte-alignment/ 这里的结构体字节对齐的数据类 ...
- iOS之内存管理-字节对齐
字节对齐 1 struct Mystruct1{ 2 char a; //1字节 3 double b; //8字节 4 int c; //4字节 5 short d; //2字节 6 }Mystru ...
- ACE的CDR中的字节对齐问题
大家应该都知道计算机中间都有字节对齐问题.CPU访问内存的时候,如果从特定的地址开始访问一般可以加快速度,比如在32位机器上,如果一个32位的整数被放在能被32模除等于0的地址上,只需要访问一次,而如 ...
- ARM字节对齐问题详解
一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这 ...
随机推荐
- (转)对.net系统架构改造的一点经验和教训
在互联网行业,基于Unix/Linux的网站系统架构毫无疑问是当今主流的架构解决方案,这不仅仅是因为Linux本身足够的开放性,更因为围绕传统Unix/Linux社区有大量的成熟开源解决方案,覆盖了网 ...
- 扯扯Java中Finalization的意义
这是Stack Overflow上关于Finalizetion意义的两段讨论,这两个观点是互为补充的. 观点1: 垃圾回收器(The garbage collector)自动在后台运行(虽然它也可以被 ...
- [ACM_图论] Sorting Slides(挑选幻灯片,二分匹配,中等)
Description Professor Clumsey is going to give an important talk this afternoon. Unfortunately, he i ...
- [游戏模版10] Win32 平面地图贴图 正
>_<:picture resource >_<:If you master the ways of mapping picture,then this problem is ...
- JPA oneToMany 级联更新
oneToMany 使用: 示例:Employee与Phone为例. 1.类定义如下: package com.vrvwh.wh01.domain; import javax.persistence. ...
- [python爬虫] Selenium定向爬取海量精美图片及搜索引擎杂谈
我自认为这是自己写过博客中一篇比较优秀的文章,同时也是在深夜凌晨2点满怀着激情和愉悦之心完成的.首先通过这篇文章,你能学到以下几点: 1.可以了解Python简单爬取图片的一些思路和方法 ...
- duilib进阶教程 -- 改进窗口拖动 (12)
现在大家应该都知道caption="0,0,0,32",是指示标题栏区了吧,如果想要整个窗口都能拖动呢? 那直接把高度改成和窗口一样不就得了~O(∩_∩)O~ 嗯,这样是可以,比如 ...
- 定义一个时钟类——Clock,它包括三个int型 成员变量分别表示时、分、秒,一个构造方法用于对三个成员变量(时、分、秒) 进行初始化,还有一个成员方法show()用于显示时钟对象的时间。其次,再定义 一个主类——TestClass,在主类的main方法中创建多个时钟类的对象,使用这 些对象调用方法show()来显示时钟的时间
package java1; public class Clock { int hhh; int mmm; int sss; Clock(int h,int m,int s) { hhh=h; mmm ...
- mysql忘记密码重置(mac)
setp1: 苹果->系统偏好设置->最下边点mysql 在弹出页面中 关闭mysql服务(点击stop mysql server) step2:进入终端输入:cd /usr/local/ ...
- win7给C盘扩容
win7给C盘扩容 需要给C盘在不重装系统的情况下进行扩容.在网上搜索了不少资料,包括使用系统自带的分区工具,PQ等软件,都没有成功.不小心看到了分区助手,使用之,迅速的解决了问题,而且解决的非常完美 ...