I've run into a EXC_BAD_ACCESS with a piece of code that deals with data serialization. The code only fails on device (iPhone) and not on simulator. It also fails only on certain data types.
Here is a test code that reproduces the problem:
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*>();
}
Guessing that it must be a memory alignment issue, I decided I want to understand the problem thoroughly. From my (limited) understanding of memory alignment, when tmp gets advanced by 2 bytes, it becomes misaligned for data types whose alignment is greater than 2 bytes:
tmp += sizeof(unsigned short);
But the test code is executed alright for int and others! It only fails for long long, double and long double.
Examining the size and alignment of each data type revealed that the failing data types are the ones that have different sizeof and __alignof values:
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
(These are the result of running the print function from "C++ data alignment and portability")
Can someone enlighten me what's causing the error? Is the difference really the cause of EXC_BAD_ACCESS? If so, by what mechanics?