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。所以,在这个调用之后不久,图像就被释放了,你得到了一个指向无人区的指针。

如果没有看到代码,我无法知道这是否是实际发生的事情,但这是一种很容易犯的错误。

这些相关问题给出了类似崩溃的提示:EXC_BAD_ACCESS调试 问题 1问题 2

最后,如果这些都没有帮助,我建议您找到问题的最小再现。很难做到这一点的方法是复制你的代码,剪掉一半,看看错误是否仍然存在,然后重复,直到你找到能重现错误的最小代码。从那里进行调试通常要容易得多(并且也可以作为 stackoverflow 问题发布!)如果您知道简单的方法,请告诉我。

于 2009-08-08T13:35:13.667 回答
1

您可能需要设置NSZombiesEnabled环境变量。这样,您的应用程序EXC_BAD_ACCESS在访问已发布的对象时不会崩溃,而是将信息性消息记录到您的控制台。这篇博文很好地解释了发生了什么以及如何在 XCode 中进行设置。无论如何,永远不要忘记在生产版本中禁用此选项,否则您的对象将永远不会被释放!

于 2009-08-08T17:36:20.837 回答