46

私はiPhone開発とXcode全般に不慣れで、EXC_BAD_ACCESS信号のトラブルシューティングを開始する方法がわかりません。エラーの原因となっている正確な行でXcodeを壊すにはどうすればよいですか?


問題の原因となっている行でXcodeを停止させることができないようですが、デバッグコンソールに次の行が表示されます。

日10月25日15:12:14jasonsmacbookTestProject [1289]:CGContextSetStrokeColorWithColor:無効なコンテキスト

日10月25日15:12:14jasonsmacbookTestProject [1289]:CGContextSetLineWidth:無効なコンテキスト

日10月25日15:12:14jasonsmacbookTestProject [1289]:CGContextAddPath:無効なコンテキスト

日10月25日15:12:14jasonsmacbookTestProject [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の質問は、initメソッド内でプロパティを設定する方法について私を混乱させるだけです。どちらの方法が最適かについては、コンセンサスが得られていないようです。

4

10 に答える 10

84

EXC_BAD_ACCESSエラーの場合、通常、解放されたオブジェクトにメッセージを送信しようとしています。これらを追跡する最良の方法は、NSZombieEnabled使用することです。

これは、オブジェクトを実際に解放することはありませんが、オブジェクトを「ゾンビ」としてラップし、通常は解放されることを示すフラグをオブジェクト内に設定することで機能します。このように、もう一度アクセスしようとしても、エラーが発生する前の状態がわかっているので、この少しの情報があれば、通常はバックトラックして問題の内容を確認できます。

これは、デバッガーが有用な情報を取得することがある場合に、バックグラウンドスレッドで特に役立ちます。

ただし、非常に重要な点は、これがデバッグコードにのみ含まれ、配布コードには含まれないことを100%確認する必要があるということです。何もリリースされていないため、アプリはリークし、リークし、リークします。これを行うように私に思い出させるために、私はこのログを私のappdelegateに入れました:

if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
  NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");

正確な行を見つけるのに助けが必要な場合は、ビルドアンドラン( CMD-R )の代わりにビルドアンドデバッグ( CMD-Y )を実行してください。アプリがクラッシュすると、デバッガーは正確にどの行を表示し、NSZombieEnabledと組み合わせて、正確な理由を見つけることができるはずです。

于 2009-10-25T21:15:46.307 に答える
17

アレイについて。この線

NSMutableArray *array = [NSMutableArray array];

実際には保持されたオブジェクトではなく、自動解放オブジェクトを提供します。おそらく次の行で保持されますが、3 行目で解放しないでください。これを見る

これが基本的なルールです。

名前が「alloc」または「new」で始まるメソッド、または「copy」を含むメソッド (たとえば、alloc、newObject、または mutableCopy) を使用してオブジェクトを作成した場合、または保持メッセージを送信した場合、オブジェクトの所有権を取得します。release または autorelease を使用して、所有しているオブジェクトの所有権を放棄する責任があります。それ以外のオブジェクトを受け取った場合は、それを解放してはなりません。

于 2009-10-25T23:04:09.353 に答える
10

Xcode 4 では、[スキーム] ドロップダウン (左上、停止ボタンの右隣) -> [スキームの編集] -> [診断] タブ -> [ゾンビ オブジェクトの有効化] をクリックして、ゾンビを有効にすることができます。

于 2011-11-10T12:37:08.040 に答える
7

Xcode/gdb は常にEXC_BAD_ACCESS.

これらの種類のエラーはautoreleasedオブジェクトで発生することが多いことに注意してください。つまり、問題の最終的な原因は、トリガーされたコール スタックにはありませんEXC_BAD_ACCESS。そんな時、NSZombieEnabled と NSAutoreleaseFreedObjectCheckEnabled が役に立ちます。

于 2009-10-25T23:01:37.947 に答える
5

古いスレッドに対する新しい回答... XCode 4 で EXC_BAD_ACCESS 例外を診断する最も効果的な方法は、Instruments を使用してアプリをプロファイリングすることです (XCode から Product/Profile をクリックし、Zombies を選択します)。これは、割り当て解除されたオブジェクトに送信されたメッセージを識別するのに役立ちます。

于 2011-11-15T11:24:54.520 に答える
2

スタンフォード CS193P クラスから: シンボルに (ブレークポイントを手動で編集して) ブレークポイントを追加するとobjc_exception_throw、何が問題なのかをよりよく把握できます。スタックトレースを台無しにします。objc_exception_throw で停止すると、多くの場合、問題の原因となったアクセス/操作を正確に振り返ることができます。

于 2009-10-25T22:23:46.637 に答える
2

もう 1 つの便利な方法は、例外が発生した直後にトリガーされるブレークポイントを設定することです。

ブレークポイント ウィンドウ (実行 – 表示 – ブレークポイント) を開き、「objc_exception_throw」と「[NSException raise]」という 2 つのシンボリック ブレークポイントを追加します。

から: http://blog.emmerinc.be/index.php/2009/03/19/break-on-exception-in-xcode/

于 2010-05-23T04:39:14.260 に答える
1

同じエラーの解決策を探しながら、ウェブから来ている他の人のために追加したかったのですが、間違いが異なりました。私の場合、キーの前に「@」を追加するのを忘れたキー名のタイプミスで NSDictionary をインスタンス化しようとしたときに同じエラーが発生しました。

NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys: myObj1, @"goodKey", myObj2, "badkey @ is missing in front", nil];
于 2011-08-13T11:59:07.257 に答える
0

ゾンビを有効にする前に、まずすべての警告を取り除くことをお勧めします (警告がある場合)。のない非 void 関数のような単純なものreturnがこのエラーを引き起こす可能性があります。警告がない場合は、他の回答が示唆するように進んでください。

于 2014-03-26T16:55:21.557 に答える