2011-10-11 17 views
8

Apple LLVM Compiler 3.0を使用し、-O3でコンパイルしたときにNSCoderで異常なクラッシャーが見つかりました。デバイス上でのみクラッシュします。 iOS 5を実行しているiPhone 4、iOS 5を実行しているiPad 2、iOS 4を実行しているiPad 1をテストしました。すべて同じようにクラッシュします。ここでは、コードの該当部分があります:NSCoderのdecodeBytesForKeyによって返されたポインタを参照解除するときにiOSデバイスでクラッシュする

typedef struct 
{ 
    NSInteger x; 
    NSInteger y; 
} 
BBPointI32; 

dataがデリファレンスされたときにEXC_BAD_ACCESSが起こる:

-(id)initWithCoder:(NSCoder*)decoder 
{ 
    if (![super init]) 
    { 
     return nil; 
    } 

    NSUInteger length = 0; 

    uint8_t* data = (uint8_t*)[decoder decodeBytesForKey:BBKey returnedLength:&length]; 

    m_value = *(BBPointI32*)data; 

    return self; 
} 

そして、ここではBBPointI32があるものです。これはではなく、 nullポインタの問題です。 GDBを添付すると、長さが8、sizeof(BBPointI)も8、データが正しいことがわかります。

私は解体を見れば

、クラッシュが起こっている上:正常に見える

ldrd r2, r3, [r0] 

を。 r0は0xb546eを含み、これはdataのアドレスです。そのメモリを調べると、期待したデータが格納されていることがわかります。興味のある人は、r2には72(それが何であるかわからない)とr3には8(おそらくはlengthの値)が含まれています。

誰もがこの問題にいくつかの光を当てることができますか?

答えて

10

ldrdは、アドレスが8バイト境界であることが必要です。 *(BBPointI32 *)データイディオムは、データが8バイト境界ではないため安全ではありません。代わりにmemcpyを使用して、構造体にバイトを取得します。

+0

ありがとうございました。この問題はコンパイラの 'ldrd'使用の決定に関連していました。 私は 'BBPointI32 *'に 'data'をキャストすると、ポインタが正しく整列していることを意味していると仮定しましたが、そうではありませんでした。したがって、代わりに: m_value = *(BBPointI32 *)data; 使用する必要があります: memcpy(&m_value、data、length); –

+0

@biorhythmist ..ちょうど陽気なtwittererではありません:) – ohhorob

+0

私は非常に似た何かを経験しています。 iPad 3で起こり、iPad 2では_not_! –

4

ARCを使用していますか?もしそうなら、私は、decodeBytesForKey:呼び出しの後でコンパイラがdecoderを解放することが自由である(したがって、戻り値が指し示すバッファを解放する)ということを信じています。

同じinterior pointer issue garbage collection hasです。デコーダの寿命を延ばすには、デコーダにCFRetain/CFReleaseを追加するか、後で[decoder self]をメソッドに追加して、その時点まで有効にしておいてください。

decoder__attribute__((objc_precise_lifetime))と注釈を付けることでこの問題を解決できる可能性がありますが、that attributeについての理解はやや曖昧です。

3

この例では、潜在的なヘルパーが疑問を持つ変数がたくさん残っています。たとえば、このunarchiverでファンキーなことがあればどうなりますか?メモリは正しく管理されていますか?

あなたが見ているクラッシュを再現することができ、-O3が有効になっている場合にのみ発生することを確認できます。最適化のために選択されていません。以下は、コーダーのメモリ管理などの外部変数を排除したクラッシュコードの削減です。以下のコードでは、すべてのオブジェクトを意図的に保持して、クラッシュが偶発的なオーバーリリースや副作用に関連する可能性を排除しています。別の答えにアンディにより示唆されるように、ARCを使用することの効果:

typedef struct 
{ 
    NSInteger x; 
    NSInteger y; 
} 
BBPointI32; 

- (void) testDecoding 
{ 
    NSString* myKey = @"Testing"; 

    // First get an coder with bytes in it 
    NSMutableData* myData = [[NSMutableData data] retain]; 
    NSKeyedArchiver* myCoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:myData]; 

    BBPointI32 encodedStruct = {1234, 5678}; 
    [myCoder encodeBytes:(const uint8_t *)&encodedStruct length:sizeof(encodedStruct) forKey:myKey]; 
    [myCoder finishEncoding]; 

    // Now decode it 
    BBPointI32 decodedStruct; 
    NSUInteger decodedLength = 0; 
    NSKeyedUnarchiver* myDecoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:myData]; 
    uint8_t* data = (uint8_t*)[myDecoder decodeBytesForKey:myKey returnedLength:&decodedLength]; 
    decodedStruct = *(BBPointI32*)data; 
    NSLog(@"Got decoded struct with x = %ld, y = %ld, length = %lu", decodedStruct.x, decodedStruct.y, decodedLength); 
} 

- (void)applicationDidFinishLaunching:(UIApplication *)application {  
    NSLog(@"Testing decoding"); 
    [self testDecoding]; 
} 

私はこれが助けるために望んでいる誰もがダイビングの基礎として使用することができないという問題をより簡潔に説明しますと思う私の勘これまで。これはLLVM 3.0の最適化バグですが、誰かが何が起こっているのかについてのよりよい理論を持っているかもしれません。

あなたの質問には言及していませんが、私のデバイス上のクラッシュで気づいた点は、不良アクセス例外の理由としてEXC_ARM_DA_ALIGNエラーが発生したことです。

decodedStruct = *(BBPointI32*)data; 

上記の行を変更することで、

http://www.galloway.me.uk/2010/10/arm-hacking-exc_arm_da_align-exception/

実際:私は同じ症状にほのめかすと、おそらくあなたはここで見ているとクラッシュのために引き起こしているようだブログ記事をGoogleで検索しました

memcpy(&decodedStruct, data, sizeof(decodedStruct)); 

クラッシュ動作が緩和されているように見え、コードは期待どおりに動作します。

+0

私の最後にはEXC_ARM_DA_ALIGNがありませんでしたが、それも私が行った変更です。ご協力いただきありがとうございます。 –

1

私はこのスレッドに「EXC_ARM_DA_ALIGN」と「EXC_BAD_ACCESS」と尋ねました。他の答えは私には役に立たなかった。このエラーは比較的シンプルなものが原因で崩壊した。私は書いた:

theArray = [[NSArray alloc] initWithObjects:@"first", @"second", @"third", 
         @"fourth", @"fifth", "sixth", nil]; 

すなわち、私は文字列リテラルの前に@を付けていました。それを元に戻してエラーを解決しました。

+0

lol - ちょうど2時間かけてこれを追跡しようとしました。ソリューションを投稿していただきありがとうございます。 – wufoo

関連する問題