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
ですか?もしそうなら、どのようなメカニズムで?