1

Objective-Cには非常に単純なコード行があります。

if ((selectedEntity != nil) && [selectedEntity isKindOfClass:[MobileEntity class]])

ときどき、理由もなく、EXC-BAD-ACCESSを使用してこのコード行でゲームがクラッシュします。通常、何かが競技場から削除される頃のように思われるので、selectedEntityが割り当て解除されたと推測すると、この結果になります既存のエンティティを選択することは不可能であることに加えて(しかし、誰が知っているか、これは私のコードでは実際には当てはまらないかもしれません...)、アクセスする前に選択されたエンティティがあるかどうかを具体的にチェックしているという事実は、私がすべきはないことを意味しますここでは問題はありません。Objective-Cはブール型の短絡をサポートすることになっていますが、編集ではないようです。短絡は問題とは何の関係もないようです。

また、時々爆発していることを知っていたので、このコードブロックの周りに@ try / @ catchを配置しましたが、それは無視されているようです(EXC-BAD-ACCESSをキャッチできないと思います)。

だから基本的に私は誰かがこれを捕まえて捨てる方法を知っているのか(ゲームがクラッシュしない限りこのエラーを気にしないので)、なぜそれが起こるのか説明できるのだろうかと思っています。Objective-Cが「nil」値で奇妙なことをすることを知っているので、オブジェクトポインタでもnilでもない奇妙なスペースを指していると思います。

編集:明確にするために、私は以下のコードが間違っていることを知っています、それは私が私のプログラムで起こっていたと私が推測していたことです。私はそれが問題を引き起こすかどうか尋ねていました-それは確かにそうです。:-)

編集:消去される前にエンティティを選択できるフリンジケースがあるようです。したがって、コードの進行は次のようになります。

selectedEntity = obj;
NSAutoreleasePool *pool = ...;
[obj release];
if (selectedEntity != nil && etc...) {}
[pool release];

したがって、自動解放プールがまだ解放されていないため、オブジェクトはnilではありませんが、保持カウントは0であるため、とにかくアクセスすることはできません...またはそれらの線に沿った何か?

また、私のゲームはシングルスレッドなので、これはスレッドの問題ではありません。

編集:私は2つの方法で問題を修正しました。まず、そのフリンジケースではエンティティの選択を許可しませんでした。次に、[entities removeObjectAtIndex:i](削除されるエンティティを削除するコード)を呼び出す代わりに、次のように変更しました。

//Deselect it if it has been selected.
if (entity == selectedEntity)
{
    selectedEntity = nil;
}

[entities removeObjectAtIndex:i];

jibが提案したように、変数を解放すると同時に変数にnilを割り当てていることを確認してください。

4

5 に答える 5

9

これは短絡とは何の関係もありません。Objective-Cはメッセージをnilに変換するため、チェックするselectedEntity != nil必要はありません(messages-to-nilはBOOLリターンタイプに対してNOを返すため)。

EXC_BAD_ACCESSはキャッチ可能な例外ではありません。これは、一般的に無効なポインタを追跡しようとすることによって引き起こされる壊滅的な障害です。

ほとんどの場合、selectedEntityが指すオブジェクトはすべて、コードが実行される前に解放されています。したがって、それはnilでも有効なオブジェクトでもありません。

NSZombiesをオンにして、再試行してください。

アプリがスレッド化されている場合、selectedEntityをスレッド間で適切に同期していますか(一般に、セカンダリスレッドからのUIのディドルはサポートされていないことに注意してください)?


あなたの投稿は、修正が次のとおりであることを示すために編集されました。

//Deselect it if it has been selected.
if (entity == selectedEntity)
{
    selectedEntity = nil;
}

[entities removeObjectAtIndex:i];

NSMutableArrayは削除時にオブジェクトを解放するため、これにより問題が修正されます。保持カウントがゼロに下がると、オブジェクトは割り当て解除され、selectedEntityは割り当て解除されたオブジェクトを指します。

于 2009-08-31T19:45:27.540 に答える
6

オブジェクト(selectedEntity)が解放され、割り当てが解除された場合、それは==nilではありません。これは任意のメモリへのポインタであり、それを延期する(if(selectedEntity!= nil)はプログラミングエラー(EXC_BAD_ACCESS)です)。

したがって、一般的なobj-cパラダイム:-

[selectedEntityリリース]; selectedEntity = nil;

于 2009-08-31T20:11:35.770 に答える
0

私はちょうどこのhttp://developer.apple.com/mac/library/qa/qa2004/qa1367.htmlを読みました。これは、あなたが得ているエラーがオブジェクトの過剰リリースの結果であることを示しています。これは、selectedEntityがゼロであるにもかかわらず、何度もリリースしたことを意味し、もう使用することはできません。

于 2009-08-31T19:47:22.577 に答える
0

OBJC_EXCEPTION_THROWにブレークポイントを設定し、実際にスローされている場所を確認します。その行は、それ自体でEXC_BAD_ACCESSをスローしてはなりません。

おそらく、例外を引き起こす可能性のあるIFブロック内で何かをしていますか?

于 2009-08-31T19:53:48.960 に答える
0
 

selectedEntity = obj;
NSAutoreleasePool *pool = ...;
[obj release];
if (selectedEntity != nil && etc...) {}
[pool release];

 

ここにダングリングポインタまたはゾンビがあります。selectedEntityは、selectedEntityを参照する直前にリリースを取得するobjを指しています。これにより、selectedEntityはnil以外になりますが、オブジェクトが無効になるため、その逆参照はクラッシュします。

objを解放するのではなく、自動解放したかったのです。

于 2009-08-31T20:15:34.343 に答える