私はiPhone開発とXCode全般に不慣れであり、_EXC_BAD_ACCESS
_シグナルのトラブルシューティングを開始する方法がわかりません。エラーの原因となっている正確な行でXCodeを中断するにはどうすればよいですか?
問題の原因となっている行でXCodeを停止させることはできませんが、デバッグコンソールに次の行が表示されます。
日10月25日15:12:14 jasonsmacbook TestProject [1289]:CGContextSetStrokeColorWithColor:無効なコンテキスト
日10月25日15:12:14 jasonsmacbook TestProject [1289]:CGContextSetLineWidth:無効なコンテキスト
日10月25日15:12:14 jasonsmacbook TestProject [1289]:CGContextAddPath:無効なコンテキスト
日10月25日15:12:14 jasonsmacbook TestProject [1289]:CGContextDrawPath:無効なコンテキスト
2009-10-25 15:12:14.680 LanderTest [1289:207] ***-[CFArray objectAtIndex:]:割り当て解除されたインスタンス0x3c4e610に送信されたメッセージ
今、私はUIGraphicsGetCurrentContext()
から取得したコンテキストに描画し、描画したいオブジェクトに渡そうとしています。
さらに試行錯誤のデバッグを行ったところ、クラスでプロパティを持っているNSMutableArray
がゾンビであることがわかりました。クラスのinit
関数に入りました。使用しているコードは次のとおりです。
_if ((self = [super init])) {
NSMutableArray *array = [NSMutableArray array];
self.terrainBlocks = array;
[array release];
}
return self;
}
_
_[array release]
_行を削除し、_EXC_BAD_ACCESS
_信号が表示されなくなったが、なぜこれが機能するのか混乱している。プロパティを使用すると、自動的に保持されるため、リークが発生しないようにinit
内から解放する必要があると考えました。私はこれがどのように機能するのか、すべてのガイドとStackoverflowの質問について完全に混乱しています。どちらの方法が最良であるかについてはコンセンサスがないようです。
EXC_BAD_ACCESSエラーについては、通常、リリースされたオブジェクトにメッセージを送信しようとしています。 [〜#〜] best [〜#〜]これらを追跡するには、 NSZombieEnabled を使用します。
これは、実際にオブジェクトを解放することなく機能しますが、「ゾンビ」としてラップし、その中に通常解放されるはずのフラグを設定します。このように、再度アクセスしようとすると、エラーを起こす前の状態がまだわかります。この少しの情報で、通常はバックトラックして問題の内容を確認できます。
これは、デバッガーが有用な情報を時々たたくときにバックグラウンドスレッドで特に役立ちます。
注:非常に重要ただし、これはデバッグコードのみであり、配布コードではないことを100%確認する必要があるということです。何もリリースされないため、アプリはリークし、リークしてリークします。これを行うことを思い出させるために、このログをappdelegateに入れます。
if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
正確な行を見つけるのに助けが必要な場合は、ビルドと実行(CMD-R)ではなく、ビルドとデバッグ(CMD-Y)を実行してください。アプリがクラッシュすると、デバッガーは正確にどの行を表示し、NSZombieEnabledと組み合わせて、正確な理由を見つけることができるはずです。
アレイについて。この線
NSMutableArray *array = [NSMutableArray array];
実際に保持されたオブジェクトではなく、自動解放オブジェクトを提供します。おそらく次の行で保持されますが、3行目でリリースしないでください。 this を参照してください
これが基本的なルールです:
名前が「alloc」または「new」で始まるメソッド、または「copy」を含むメソッド(たとえば、alloc、newObject、またはmutableCopy)を使用してオブジェクトを作成する場合、または保持メッセージを送信する場合、オブジェクトの所有権を取得します。リリースまたは自動リリースを使用して、所有するオブジェクトの所有権を放棄する責任があります。オブジェクトを受け取ったときは、それをリリースしてはなりません。
Xcode 4では、スキームドロップダウンをクリックしてゾンビを有効にできます(左上、停止ボタンの右隣)->スキームの編集->診断タブ->ゾンビオブジェクトの有効化
Xcode/gdbは常にEXC_BAD_ACCESS
で中断します。呼び出しスタックを上に移動して、それをトリガーしたコードを見つける必要があります。
これらの種類のエラーはautoreleased
オブジェクトで頻繁に発生することに注意してください。つまり、問題の最終的な原因はEXC_BAD_ACCESS
をトリガーした呼び出しスタックにありません。 NSZombieEnabledとNSAutoreleaseFreedObjectCheckEnabledが役立つのはそのときです。
古いスレッドに対する新しい答え... XCode 4でEXC_BAD_ACCESS例外を診断する最も効果的な方法は、Instrumentsを使用してアプリのプロファイルを作成することです(XCodeから[Product/Profile]をクリックし、[Zombies]を選択します)。これは、割り当て解除されたオブジェクトに送信されたメッセージを識別するのに役立ちます。
Stanford CS193Pクラスから:symbolobjc_exception_throw
にブレークポイントを(手動で、ブレークポイントを編集することで)追加すると、何がうまくいかなかったかをよりよく把握できます。物を覆い隠してスタックトレースを台無しにします。 objc_exception_throwで停止すると、問題の原因となったアクセス/操作を正確に振り返ることができます。
別の有用なアプローチは、例外が発生した後に直接トリガーするブレークポイントを設定することです:
ブレークポイントウィンドウを開き(実行-表示-ブレークポイント)、「objc_exception_throw」および「[NSException raise]」という2つのシンボリックブレークポイントを追加します。
From: http://blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/
Webから来ている他の人に追加したかったのは、同じエラーであるが異なるミスのソリューションを検索することでした。私の場合、キーの前に「@」を追加するのを忘れたキー名のタイプミスでNSDictionaryをインスタンス化しようとしたときに同じエラーが発生しました:
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: myObj1, @"goodKey", myObj2, "badkey @ is missing in front", nil];
私は同じ答えを見逃さなかったことを願っていますが、プロジェクトの依存関係またはフレームワークと互換性がない可能性がある古いiOSバージョンのシミュレータで実行しているため、一部のプロジェクトでこのエラーがスローされる可能性があることがわかりました。 iPhone 4Sのような、より古いシミュレーターのバージョンで起こっていることに気づく前に、私はこれらの1つを追い続けていましたが、アプリはサポートを試みることすらありませんでした。
より詳細なエラーメッセージを受け取ったのは良かったのですが、それが発生したフレームワークの責任だと思います...とにかく、これはかなり一般的な検索の着陸であり、おそらくこれは誰かがひどく混乱するのを助けるかもしれません私は自分自身を見つけたように。
ゾンビを有効にする前に、まず警告がある場合はすべて削除することをお勧めします。 return
のない非void関数のような単純なものがこのエラーを引き起こす可能性があります。警告が表示されない場合は、他の回答が示すように進みます。