0
Program received signal:  “EXC_BAD_ACCESS”.
(gdb) bt
#0  0x30011940 in objc_msgSend ()
#1  0x30235f24 in CFRelease ()
#2  0x308f497c in -[UIImage dealloc] ()
#3  0x30236b78 in -[NSObject release] ()
#4  0x30a002a0 in FlushNamedImage ()
#5  0x30250a26 in CFDictionaryApplyFunction ()
#6  0x30a001a4 in _UISharedImageFlushAll ()
#7  0x30a00738 in +[UIImage(UIImageInternal) _flushCacheOnMemoryWarning:] ()
#8  0x3054dc80 in _nsnote_callback ()
#9  0x3024ea58 in _CFXNotificationPostNotification ()
#10 0x3054b85a in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#11 0x3054dbc0 in -[NSNotificationCenter postNotificationName:object:] ()
#12 0x30a00710 in -[UIApplication _performMemoryWarning] ()
#13 0x30a006a8 in -[UIApplication _receivedMemoryNotification] ()
#14 0x30a005d8 in _memoryStatusChanged ()
#15 0x30217416 in __CFNotificationCenterDarwinCallBack ()
#16 0x3020d0b0 in __CFMachPortPerform ()
#17 0x30254a76 in CFRunLoopRunSpecific ()
#18 0x3025416a in CFRunLoopRunInMode ()
#19 0x320452a4 in GSEventRunModal ()
#20 0x308f037c in -[UIApplication _run] ()
#21 0x308eea94 in UIApplicationMain ()
#22 0x00002096 in main (argc=1, argv=0x2ffff514)

現在、私のプログラムには非常に奇妙なエラーがあります。起こる時もあれば、起こらない時もあります。しかし、ここに何が起こっているかの要約があります:

プログラムの起動時:

  • 保存されたデータ (13 要素で構成される短い plist のみ) が存在する場合は、それが読み込まれます。
  • 1014 個の文字列を含む巨大な plist が NSMutableDictionary にロードされます。
  • 78 個の文字列を含む別の plist が NSArray にロードされます。
  • .mp4 ムービーが再生されます。

エラーは、OpenGL ES View が削除され、ユーザーが NSMutableDictionary の 1014 文字列のいずれかの文字列を表示しようとしている部分で発生します。

このエラーは、シミュレータでは発生しません。iPhoneでのみ発生し、正常に動作することもありますが、クラッシュすることもあります。

しかし、スタックトレースを読んだところCFDictionaryApplyFunctionが入っていたので、原因の一つではないかと考えました。シミュレーターでは非常に高速に読み取り、plist の辞書全体が瞬時に読み込まれるのに対し、デバイスでは読み取りが遅いためですか? 正直なところ、辞書がどのように機能するのか正確にはわかりません。1014 文字列すべてを瞬時に読み取るのか、それとも他のスレッドを使用してゆっくりと読み取るのか? ご意見をお聞かせください。ありがとうございました。

4

2 に答える 2

5

を取得した場合EXC_BAD_ACCESS、多くの場合、そこにないオブジェクトでメソッドを呼び出そうとしていることを意味します。おそらく、割り当てが解除されているためです。

トレースのほぼ途中で、次のようないくつかのメモリ警告呼び出しがあります。

#12 0x30a00710 in -[UIApplication _performMemoryWarning] ()

これにより、コードが直接クラッシュを引き起こしているのではなく、メモリが不足したときのシステム通知が発生しているように見えます。

フレーム #0 に近づくと、UIImageオブジェクトのキャッシュをクリアしようとしているように見えますが、これは不正なアクセスのようです。

これに基づいて、便利なコンストラクターの自動解放された戻り値にポインターを割り当てていると推測されます。オブジェクトは自動解放され、イメージを直接使用しないので問題ないと思うかもしれませんが、メモリ警告がそれにアクセスしようとします。例えば:

@interface MyClass {
  UIImage* myImage;
}
// ...
- (id) init {  /* the usual stuff */
  myImage = [UIImage imageNamed:@"bob_the.png"];
  return self;
}

この例では、 に保持プロパティが設定されていてもmyImage、 で値を設定しない限り、実際には画像は保持されませんself.myImage。したがって、この呼び出しの直後にイメージがリリースされ、無人地帯へのポインターが得られます。

コードを見ない限り、それが実際に起こっていることなのかどうかはわかりませんが、これは犯しやすい間違いの 1 つです。

これらの関連する質問は、同様のクラッシュに関するヒントを提供します:EXC_BAD_ACCESSデバッグの 質問 1および質問 2

最後に、それでも解決しない場合は、問題の最小限の再現を見つけることをお勧めします。これを行う難しい方法は、コードをコピーし、半分を切り取り、エラーがまだ存在するかどうかを確認し、エラーを再現する最小のコードが見つかるまで繰り返すことです。通常、そこからデバッグする方がはるかに簡単です (また、stackoverflow の質問として投稿することもできます!) 簡単な方法を知っている場合は、お知らせください。

于 2009-08-08T13:35:13.667 に答える
1

NSZombiesEnabled環境変数を設定することをお勧めします。EXC_BAD_ACCESSこのようにして、リリースされたオブジェクトにアクセスするときにアプリがクラッシュすることはなく、コンソールに情報メッセージを記録します。このブログ投稿では、XCodeで何が起こり、どのように設定するかについて説明しています。とにかく、本番リリースでこのオプションを無効にすることを決して忘れないでください。そうしないと、オブジェクトがリリースされないからです。

于 2009-08-08T17:36:20.837 に答える