【问题标题】:Crash when trying to call [super didReceiveMemoryWarning]尝试调用 [super didReceiveMemoryWarning] 时崩溃
【发布时间】:2012-05-13 14:10:46
【问题描述】:

我有一个应用程序,我收集了我无法重现的崩溃报告。我有一个视图控制器,它在处理自己的内存警告时只是调用[super didReceiveMemoryWarning](是的,我知道我不需要这样做,但这也不能解决我现在遇到的问题)。一旦父 UIViewController 尝试调用 purgeMemoryForReason 它就会崩溃

这是相关的跟踪信息:

Exception Type:  SIGSEGV
Exception Codes: SEGV_ACCERR at 0x90000008
Crashed Thread:  0

Thread 0 Crashed:
0   libobjc.A.dylib                     0x361dbf78 objc_msgSend + 16
1   UIKit                               0x31fbf499 -[UIViewController purgeMemoryForReason:] + 65
2   MyApp                               0x00016f0d -[AttributesViewController didReceiveMemoryWarning] (AttributesViewController.m:76)
3   Foundation                          0x30c5b4ff __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 19
4   CoreFoundation                      0x34d86547 ___CFXNotificationPost_block_invoke_0 + 71
5   CoreFoundation                      0x34d12097 _CFXNotificationPost + 1407
6   Foundation                          0x30bcf3eb -[NSNotificationCenter postNotificationName:object:userInfo:] + 67
7   Foundation                          0x30bd0c1b -[NSNotificationCenter postNotificationName:object:] + 31
8   UIKit                               0x31f8a271 -[UIApplication _performMemoryWarning] + 81
9   UIKit                               0x31f8a36b -[UIApplication _receivedMemoryNotification] + 175
10  libdispatch.dylib                   0x30de42e1 _dispatch_source_invoke + 517
11  libdispatch.dylib                   0x30de1b81 _dispatch_queue_invoke$VARIANT$mp + 53
12  libdispatch.dylib                   0x30de1ec1 _dispatch_main_queue_callback_4CF$VARIANT$mp + 157
13  CoreFoundation                      0x34d8d2ad __CFRunLoopRun + 1269
14  CoreFoundation                      0x34d104a5 CFRunLoopRunSpecific + 301
15  CoreFoundation                      0x34d1036d CFRunLoopRunInMode + 105
16  GraphicsServices                    0x3600c439 GSEventRunModal + 137
17  UIKit                               0x31e06e7d UIApplicationMain + 1081
18  MyApp                               0x0000243b main (main.m:15)

我希望我能重现该错误,但无论我在测试设备或模拟器上触发内存警告多少次,我都无法让这种情况发生。任何关于我可能寻找的帮助将不胜感激,因为我已经尝试寻找并且没有找到任何指向我潜在问题的信息。谢谢!

编辑:正如我所说,我没有在didReceiveMemoryWarning做任何事情:

- (void) didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

是的,我知道我不需要这样做。我计划删除这段代码(我什至不知道为什么我仍然有它),但我想确保我已经修复了我的问题的根源。我也没有在AttributesViewController 中实现viewDidUnload。我还应该提到我正在使用 ARC,但我不确定这是否重要。

根据我收到的反馈,使用相机时会出现内存警告(UIImagePickerController 源类型为UIImagePickerControllerSourceTypeCamera)。 AttributesViewController 由视图控制器以模态方式呈现,在呈现 UIImagePickerController 的一层之上两层,它们不共享任何对象或其他数据。我知道相机经常会导致内存警告,所以我不确定UIImagePickerController 是否有任何关联,除了它占用内存。

我已将 Xcode 设置为始终运行分析器,但没有出现任何问题。我还通过 Zombies and Leaks 工具运行了代码,但无法重现问题或发现任何其他问题。

【问题讨论】:

  • 你试过启用僵尸吗?

标签: objective-c ios memory-management segmentation-fault


【解决方案1】:

您在 didReceiveMemoryWarning 中做什么?你在释放任何内存吗?关闭视图?什么?邮政编码! [我看到您发布了更多代码。谢谢。]

否则,导致 didReceiveMemoryWarning 的问题将无法解决,因此将来尝试分配更多内存(即分配新对象)的尝试可能会开始失败。因此,任何依赖于这些对象的代码都会失败。你的代码是否真的在检查你分配新东西的所有时间的返回值?

更重要的是,您确定收到这些内存警告的原因了吗?当然,优雅地处理低内存情况是至关重要的,但如果人为可能的话,防止它们同样(如果不是更重要的话)重要。您是否通过分析器(command+shift+B)运行代码?您是否分析过您的应用程序(command+I)以识别任何泄漏源?

更新:

感谢您分享您的说明。坦率地说,我的想法不多,但还有一些想法:

  1. 当您无法重现问题时,很难诊断(更不用说修复)。这似乎真的是首要任务。如果您在 iPhone 4 或 4S 上进行测试,您将享受 512MB DRAM,但 3G 只有 256MB,而 3 有 128MB。您是否在较新的设备上进行测试,而用户可能拥有less capable devices?或者您的崩溃日志是否来自具有同等装备的设备?似乎您可能会在不同的时间收到 didReceiveMemoryWarning,具体取决于设备配置,因此可能会更难显示用户看到的崩溃。

  2. 为什么应用程序会崩溃?这可能源于didReceiveMemoryWarning 无法释放足够的内存以继续操作(即后续allocs 所需对象失败),但我不确定您的崩溃日志是否表明了这一点。该日志让我想知道您是否正在执行任何Key Value Observing 或任何NSNotificationCenter 逻辑?我问是因为你可以想象在没有移除观察者的情况下释放了一个观察到的物体而引起的问题。我之所以这么问,是因为我看到了 addObserver:selector:name:object: 引用,但不知道这是否是 Cocoa 在后台执行的操作,或者您的应用程序是否自己执行。 (而且可能不相关。)是否所有崩溃日志都显示类似的调用堆栈?

  3. 应用程序是否通常检查以确保它的各种指针不为零?同样,我预计崩溃日志会略有不同,但似乎在检查 nil 值时要格外谨慎,以确保 purgeMemoryForReason 没有在你的幕后发布任何东西。

  4. 我想唯一的其他建议是,您的所有 didReceiveMemoryWarning 和 viewDidUnload 是否都在尽可能地释放内存警告的影响,从而确保应用程序能够在这种内存不足的情况下幸存下来。看起来标准的didReceiveMemoryWarning 会尝试卸载不活动的视图,因此您可能希望确保这些视图正确清理内存。根据Managing Your Memory Efficiently,您要确保在viewDidUnloaddidReceiveMemoryWarning 中释放视图对象。

抱歉,我没有更具建设性的建议。希望其他人能够提出一些更好的想法。

【讨论】:

  • 我在帖子中添加了更多细节。
  • 我也相应地修改了我的答案,但我的想法已经不多了。
  • 感谢您的反馈。我会接受这些建议并仔细检查我的代码,看看是否能找到我还没有看到的任何内容。
  • 我确实发现该视图控制器上有一个保留视图,我在viewDidUnload 中没有将其设置为 nil。自从我找到了这个,我还找到了其他一些我需要这样做的地方。几周前我做了这个修复,还没有收到关于这个问题的另一个崩溃报告,所以我认为它做到了。我以为我已经完成了所有这些,所以我很高兴你提到了它,否则我可能不会再看了。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多