字节对齐导致的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划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这 ...
随机推荐
- 第十八章:Android 打包部署
Andriod应用程序如果要在手机或模拟器上安装,必须要有签名! 1.签名的意义 为了保证每个应用程序开发商合法ID,防止部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序, ...
- Android开发学习总结——Android开发的一些相关概念
一.什么是3G.4G 1995年问世的第一代模拟制式手机(1G)只能进行语音通话. 1996到1997年出现的第二代GSM.CDMA等数字制式手机(2G)便增加了接收数据的功能 3G指的是第三代移 ...
- windows下使用体验更好的控制台——ConsoleZ
转做前端开发以来,每天使用最频繁的工具就是控制台了,git提交代码要用,npm安装node包也要用,grunt task 也要用,可是系统自带的cmd太难用了, 那么问题就来了: "wind ...
- [ACM_几何] UVA 11300 Spreading the Wealth [分金币 左右给 最终相等 方程组 中位数]
Problem A Communist regime is trying to redistribute wealth in a village. They have have decided to ...
- JQuery以JSON方式提交数据到服务端
JQuery将Ajax数据请求进行了封装,从而使得该操作实现起来容易许多.以往我们要写很多的代码来实现该功能,现在只需要调用$.ajax()方法,并指明请求的方式.地址.数据类型,以及回调方法等.下面 ...
- C# VS JAVA 差异 (未完待续)
1. 静态构造函数 C#中有静态构造函数, Java中没有静态构造函数.其实Java中有一个类似静态构造函数的东东,称作静态初始化,或者静态代码块,可以通过这样的代码实现相同的功能: 但是Java中静 ...
- HTML5 ——本地存储
目录 一.HTML4客户端存储 1.1.提交表单发送到服务器的信息 1.2.客户端本地存储概要 二.localStorage 2.1.添加 2.2.取值 2.3.修改 2.4.删除 2.5.跨页面与跨 ...
- Redis教程(九):主从复制配置实例
转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/136.html 一.Redis的Replication: 这里首先需要说明 ...
- Nagios学习笔记三:配置Nagios
1.Nagios的主配置文件 Nagios的主配置文件为nagios.cfg,其语法非常简洁,通常#开头的行为注释行,而参数的设置格式为<parameter>=<value>: ...
- python判断文件和目录是否存在
#Python的os.path模块提供了 isdir() 和 isfile()函数,请导入该模块,并调用函数判断指定的目录和文件是否存在. import os print os.path.isdir( ...