2

配列を反復処理するコードがいくつかあります。オブジェクトを追加できるように、2 番目の可変配列を追加しています。これは、反復が完了した後に削除したいと考えています。ただし、作成した 2 番目の配列にオブジェクトを追加しようとすると、不正なアクセス エラーが発生します。追加しようとしているオブジェクトは、この配列に追加するだけでなく、あらゆる種類のものに使用できるため、これは私を混乱させます。これにより、おそらくアレイが解放されているのではないかと考えたので、それを保持しましたが、効果はありませんでした. コードは次のとおりです。

    CCTMXObjectGroup *objectGroup = [ self objectGroupNamed: @"object" ];
    NSMutableArray *objectsToRemove = [ NSMutableArray array ];
    for ( NSDictionary *object in [ objectGroup objects ] ) {
        [ objectsToRemove addObject: object ]; // crash occurs here
        // name, type, x, y, width, height
        NSString *name = [ object valueForKey: @"name" ];
        if ( [ name isEqualToString: @"sprite" ] ) {
            [ self createSpriteFromObject: object ];
        } else if ( [ name isEqualToString: @"spriteController" ] ) {
            [ self createSpriteControllerFromObject: object ];
        }
    }

addObject 行を削除すると、クラッシュは発生しなくなります。これがキッカーです。クラッシュは 6 回目の反復でのみ発生するようです。コードをステップ実行すると、追加している可変配列と追加しているオブジェクトの両方が問題ないように見えます (リリースされていません)。では、なぜ不正なアクセスエラーが発生するのでしょうか?

編集

CoreFoundation`-[__NSArrayM addObject:]:
0x23c39e0:  pushl  %ebp
0x23c39e1:  movl   %esp, %ebp
0x23c39e3:  pushl  %edi
0x23c39e4:  pushl  %esi
0x23c39e5:  subl   $16, %esp
0x23c39e8:  calll  0x23c39ed                 ; -[__NSArrayM addObject:] + 13
0x23c39ed:  popl   %edi
0x23c39ee:  movl   1512267(%edi), %eax
0x23c39f4:  movl   %eax, 4(%esp)
0x23c39f8:  movl   8(%ebp), %esi
0x23c39fb:  movl   %esi, (%esp)
0x23c39fe:  calll  0x24e35c8                 ; symbol stub for: objc_msgSend
0x23c3a03:  movl   1512287(%edi), %ecx
0x23c3a09:  movl   %eax, 12(%esp)
0x23c3a0d:  movl   16(%ebp), %eax
0x23c3a10:  movl   %eax, 8(%esp)
0x23c3a14:  movl   %ecx, 4(%esp)
0x23c3a18:  movl   %esi, (%esp)
0x23c3a1b:  calll  0x24e35c8                 ; symbol stub for: objc_msgSend
0x23c3a20:  addl   $16, %esp ; bad access code 2
0x23c3a23:  popl   %esi
0x23c3a24:  popl   %edi
0x23c3a25:  popl   %ebp
0x23c3a26:  ret    
0x23c3a27:  nopw   (%eax,%eax)

libsystem_sim_c.dylib`bzero$VARIANT$sse42:
0x1f9c200:  pushl  %ebp
0x1f9c201:  movl   %esp, %ebp
0x1f9c203:  pushl  %edi
0x1f9c204:  movl   8(%ebp), %edi
0x1f9c207:  movl   12(%ebp), %edx
0x1f9c20a:  xorl   %eax, %eax
0x1f9c20c:  cmpl   $80, %edx
0x1f9c20f:  jg     0x1f9c24c                 ; bzero$VARIANT$sse42 + 76
0x1f9c211:  cmpl   $12, %edx
0x1f9c214:  jge    0x1f9c226                 ; bzero$VARIANT$sse42 + 38
0x1f9c216:  testl  %edx, %edx
0x1f9c218:  je     0x1f9c246                 ; bzero$VARIANT$sse42 + 70
0x1f9c21a:  movb   %al, (%edi) ; bad access code 2
0x1f9c21c:  incl   %edi
4

2 に答える 2

2
NSMutableArray *objectsToRemove = [ NSMutableArray array ];
for ( NSDictionary *object in [ objectGroup objects ] ) {
    [ objectsToRemove addObject: object ]; // crash occurs here

そこでクラッシュが発生している場合、それは何の関係もありobjectsToRemoveません(表示していないコードがない限り)。

それobjectは文庫であることを意味します。おそらく、それは下からリリースされましたobjectGroup。ゾンビ検出をオンにして、アプリを再実行します。

注:新しいときにこのようなものをデバッグするのは気が遠くなるかもしれません。いくつかのヒント:

•アセンブリコードを見つめている場合は、ほぼ確実に雑草の中にいることになります。

•Foundationフレームワークメソッドでクラッシュしている場合、これらのメソッドはMacまたはiOSデバイスを起動するために何億回も実行されるため、バグが他の場所にあることがほぼ保証されます。それらが機能すると仮定すると、安全な賭けです。

于 2013-01-13T18:15:42.183 に答える
0

問題は NSMutableArray の初期化にあることが判明しました。私が使用していた:

NSMutableArray *objectsToRemove = [ NSMutableArray array ];

あるべきとき:

NSMutableArray *objectsToRemove = [ NSMutableArray arrayWithCapacity: 10 ];
于 2013-01-14T06:00:39.283 に答える