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 发现原来是跟字节对齐有关,下面是几篇不错的文章:
(第四条)作者们都提到了使用 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*转换,强制使用老版本。**参考: