我遇到EXC_BAD_ACCESS
了一段处理数据序列化的代码。该代码仅在设备(iPhone)上失败,而不在模拟器上失败。它也仅在某些数据类型上失败。
这是重现问题的测试代码:
template <typename T>
void test_alignment() {
// allocate memory and record the original address
unsigned char *origin;
unsigned char *tmp = (unsigned char*)malloc(sizeof(unsigned short) + sizeof(T));
origin = tmp;
// push data with size of 2 bytes
*((unsigned short*)tmp) = 1;
tmp += sizeof(unsigned short);
// attempt to push data of type T
*((T*)tmp) = (T)1;
// free the memory
free(origin);
}
static void test_alignments() {
test_alignment<bool>();
test_alignment<wchar_t>();
test_alignment<short>();
test_alignment<int>();
test_alignment<long>();
test_alignment<long long>(); // fails on iPhone device
test_alignment<float>();
test_alignment<double>(); // fails on iPhone device
test_alignment<long double>(); // fails on iPhone device
test_alignment<void*>();
}
猜测这一定是内存对齐问题,我决定彻底了解这个问题。根据我对内存对齐的(有限)理解,当tmp
提前 2 个字节时,对于对齐大于 2 个字节的数据类型,它会变得不对齐:
tmp += sizeof(unsigned short);
但是测试代码对于int
和其他人执行得很好!它只对long long
,double
和失败long double
。
检查每种数据类型的大小和对齐方式表明,失败的数据类型是具有不同sizeof
和__alignof
值的数据类型:
iPhone 4:
bool sizeof = 1 alignof = 1
wchar_t sizeof = 4 alignof = 4
short int sizeof = 2 alignof = 2
int sizeof = 4 alignof = 4
long int sizeof = 4 alignof = 4
long long int sizeof = 8 alignof = 4 // 8 <> 4
float sizeof = 4 alignof = 4
double sizeof = 8 alignof = 4 // 8 <> 4
long double sizeof = 8 alignof = 4 // 8 <> 4
void* sizeof = 4 alignof = 4
iPhone Simulator on Mac OS X 10.6:
bool sizeof = 1 alignof = 1
wchar_t sizeof = 4 alignof = 4
short int sizeof = 2 alignof = 2
int sizeof = 4 alignof = 4
long int sizeof = 4 alignof = 4
long long int sizeof = 8 alignof = 8
float sizeof = 4 alignof = 4
double sizeof = 8 alignof = 8
long double sizeof = 16 alignof = 16
void* sizeof = 4 alignof = 4
(这些是从“C++ 数据对齐和可移植性”运行打印功能的结果)
有人能告诉我是什么导致了错误吗?差异真的是原因EXC_BAD_ACCESS
吗?如果是这样,通过什么机制?