crash:EXC_ARM_DA_ALIGN(关于内存对齐,memcpy)
crash:EXC_ARM_DA_ALIGN(关于内存对齐,memcpy)
问题描述
在iOS game开发时做内存拷贝时出现了 crash:EXC_ARM_DA_ALIGN,debug版本不会出现,release版本只在部分机器上出现(ipad 1(iOS7),ipod touch 5(iOS7,iOS8), iphone5c(iOS9)).
所以初步猜想是release编译优化导致的,从crash日志中只看到是某个函数,无法定位在哪一行代码,所以就添加日志后重新release,主要代码如下:
uint32_t scriptLen = *(uint32_t*)(pScriptBegin);
uint32_t prologLen = *(uint32_t*)(pScriptBegin + 4);
uint32_t scriptVer = *(uint32_t*)(pScriptBegin + 8);
jzyx::Logger::getInstance()->onInfo(StringUtils::format("sl,pl,sv = [%u, %u, %u]", scriptLen, prologLen, scriptVer).c_str());
uint32_t checkCode = scriptLen + prologLen + scriptVer;
uint32_t codePos = floor(scriptLen * 0.6);
uint32_t readCode = *(uint32_t*)(pScriptBegin + codePos);
jzyx::Logger::getInstance()->onInfo(StringUtils::format("cc,cp,rc = [%u, %u, %u]", checkCode, codePos, readCode).c_str());
然后加入两行日志后release也不崩溃了。。。更加相信是编译器优化导致
字节对齐
后来搜索了一下 EXC_ARM_DA_ALIGN 发现原来是跟字节对齐有关,下面是几篇不错的文章:
http://www.cnblogs.com/zouzf/p/4455167.html
http://justinyan.me/post/1609 (第四条)
http://discuss.cocos2d-x.org/t/problems-with-exc-bad-access-in-ccbreader/4502
作者们都提到了使用 memcpy 替换我上面的赋值代码,替换之后 release 版本确实不再出现 EXC_ARM_DA_ALIGN。代码如下:
uint32_t scriptLen, prologLen, scriptVer;
memcpy((void*)&scriptLen, (const void*)pScriptBegin, 4);
memcpy((void*)&prologLen, (const void*)(pScriptBegin + 4), 4);
memcpy((void*)&scriptVer, (const void*)(pScriptBegin + 8), 4);
uint32_t codePos = floor(scriptLen * 0.6);
uint32_t readCode;
memcpy((void*)&readCode, (const void*)(pScriptBegin + codePos), 4);
使用 memcpy 还不够,说不定你在xcode6打包的ok,但是xcode7就会crash。因为 memcpy 有多个版本,不同的xcode版本优化也不一样,需要将参数加上void*转换,强制使用老版本。参考:How do the ARM Compilers handle memcpy()?