您的位置:首页 > 移动开发 > IOS开发

从一个EXC_ARM_DA_ALIGN的crash来看ios3.2以后内存对齐问题

2013-08-05 11:03 453 查看
/article/10539810.html

今天在Iphone4调试的时候,遇到一个EXC_ARM_DA_ALIGN。用Iphone 3G(IOS3.1.2)调试之则不出现。因为出问题的代码乃一个库文件里面的,函数大致如下:

void f(const char * pBuffer, uint64_t * pDesLLong)

{

(*(uint64_t *)pDesLLong) = (*(uint64_t *)pBuffer);

...

}

查看crash log文件,发现是由于产生了一个EXC_ARM_DA_ALIGN 的 Exception。google之,找到一位老外兄弟言:IOS3.2以及之后的版本,开发者需要考虑内存对齐的问题。http://byteclub.com/blog/44-development/85-memory-alignment-errors-on-iphone-os-3-2

那么,它是几字节对齐呢?根据上面这位牛哥提供的资源,查到了这样一篇比较系统的文档,知道它是4字节对齐得(word)(https://brewx.qualcomm.com/bws/content/gi/common/appseng/en/knowledgebase/docs/kb95.html

那么问题就很明显了:如果上面那两个指针pBuffer和pDestLong所指的地址不是4的倍数,就会触发一个对齐的异常EXC_ARM_DA_ALIGN。那么这个问题怎么解决呢?前面的文档中言,使用memcpy来代替type casting来做赋值。于是我将代码改为:

memcpy((char*)pDestLong, (char*)pBuffer, sizeof(uing64_t));

在Debug版本下运行之,果然有效。可是当我编出一个Release版本的时候,问题又出现了。为何?

第一印象一定是memcpy是否被优化掉了。于是google “memcpy optimize”,发现以下这个优化代码:

void * memcpy(void * dst, void const * src, size_t len)

{

long * plDst = (long *) dst;

long const * plSrc = (long const *) src;


if (!(src & 0xFFFFFFFC) && !(dst & 0xFFFFFFFC))

{

while (len >= 4)

{

*plDst++ = *plSrc++;

len -= 4;

}

}


char * pcDst = (char *) plDst;

char const * pcDst = (char const *) plSrc;



while (len--)

{

*pcDst++ = *pcSrc++;

}


return (dst);

}


第一句话这个赋值,如果传入的指针不是一个四字节对齐的指针,即所指地址不是4的倍数,那么就会引发一个EXC_ARM_DA_ALIGN。如果真是这样的话,解决方案就必须自己写一个老版本的memcpy函数了:

void * memcpy(void * dst, void const * src, size_t len)

{

char * pDst = (char *) dst;

char const * pSrc = (char const *) src;



while (len--)

{

*pDst++ = *pSrc++;

}


return (dst);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: