EXC_BAD_ACCESS の話題が Stack Overflow で上がっていた。
Break on EXC_BAD_ACCESS in XCode? - Stack Overflow
メモリ解放済みのインスタンスへアクセスする時にこのエラーが発生することが多い。デバッグの方法として NSZombieEnabled が紹介されていた。これを使うと解放済みのインスタンスへアクセスすると EXC_BAD_ACCESS の代わりに例外が発生し、エラー原因が発見しやすくなる。
CocoaDev の解説:
CocoaDev: NSZombieEnabledサンプルプログラムを作って試してみよう。
サンプル:NSZombieEnabledStudy.zip
コードは簡単で、インスタンス変数 _data を初期化後すぐに release し、後でボタンが押された時にこれを参照する。
@interface AppController : NSObject {
NSData* _data;
}
-(IBAction)click:(id)sender;
@end
@implementation AppController
- (void)awakeFromNib
{
if(getenv("NSZombieEnabled") ||
getenv("NSAutoreleaseFreedObjectCheckEnabled")) {
NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
}
_data = [[NSData alloc] init];
[_data release];
}
-(IBAction)click:(id)sender
{
NSLog(@"_data=%@", [_data description]);
}
実行中...
プログラムはシグナルを受信しました:“EXC_BAD_ACCESS”。
続いて NSZombieEnabled を有効にしてみよう。
NSZombieEnabled を有効にする方法はアプリ起動時の引数に与える方法と gdbの設定ファイル(~/.gdbinit)に指定する方法があるようだ。
(参考)
今回は前者の方法を試してみた。Xcode で実行可能ファイルの「情報を見る」を開く。
「環境に設定される変数」へ 名前 "NSZombieEnabled"、値 "YES" として指定する。
デバッグ実行してみる。
NSZombieEnabledStudy[15646:813] NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!
NSZombieEnabledStudy[15646:813] *** -[NSConcreteData description]: message sent to deallocated instance 0x148e90
(gdb)
EXE_BAD_ACCESS の代わりに問題となった箇所が表示されるようになった。これはいい。
※なお、通常の実行(Cmd+R)ではメッセージは出ない。デバッグ実行(Cmd+Y)する。
※なお、通常の実行(Cmd+R)ではメッセージは出ない。デバッグ実行(Cmd+Y)する。