iOS应用程序在未收到低内存警告的情况下耗尽内存。

12

我有一个现有的应用程序,在其中进行了最近的一些更改,并对这些更改进行了测试。该应用在我所测试的每个iPad上(iOS 4和iOS 5)都能完美地工作。在我的应用程序中加载了多个(50+)图像密集视图之后,我会收到低内存警告,并调用了我的viewDidUnload方法,它们会恰当地置空所有控件,我的内存中图像缓存也会清除,然后应用继续正常运行。

然而,在iPhone 4和iPhone4s(iOS 5.0.1和iOS 5.1)上,我遇到了一个问题,我的应用程序在没有收到任何低内存警告的情况下就耗尽了内存。经过加载多个不同的视图后,最终会出现一个新视图,它大部分都是空白的,并且在控制台上看到内存分配消息,整个手机变得无响应,有时会强制退出我的应用程序。

此问题发生在不同的特定视图上,因此与任何一个视图都无关,只与时间累积的内存有关。我还确认我没有任何内存泄漏。

这个现有的问题很类似:

IOS app killed for Low Memory but no Memory Warning received

那个答案表明,如果我陷入了循环,这种情况可能会发生,但我相当确定我的代码没有陷入任何循环。我只是从一个视图点击到另一个视图,在UINavigationController中加载了几个图像。此外,另一个问题具体发生在iPad上,在iPad上我没有看到这个问题,只有iPhone上才有。

顺便说一下,我尝试通过NotificationCenter注册低内存通知,并在我的应用程序委托中有一个applicationDidReceiveMemoryWarning方法,并在两个断点处都设置了断点,但都没有被调用。此外,在调试器控制台中也没有低内存消息显示。

有什么想法可能正在发生什么?


添加于2012年3月26日:

有趣的是,当我在新的iPad上测试我的应用程序时,它出现了与iPhone 4和4s上看到的相同问题,即无法收到低内存通知。因此,我想知道是否遇到了与这个主题相同的问题:

The New iPad: Low Memory Warnings Not Appearing?

但是,那个主题上的开发人员正在测试一个仅适用于iPad的应用程序,因此不会在任何iPhone上测试并找到相同的问题。

我进行了一些广泛的测试,并列出了我正确接收低内存警告的设备列表以及我从未收到它的设备列表。到目前为止,我只在iOS5或更高版本上看到了这个问题,但在安装了iOS 5.0和5.1的iPad1上,我没有看到这个问题,因此这不仅仅是所有iOS 5设备上的问题。

以下是该列表:

正确的低内存警告

iPad1 4.2.1
iPad1 5.0
iPad1 5.1
iPad2 4.3.3
iPhone3G 4.2.1
iPod 3G 4.3.3
iPhone4 4.3.3

没有低内存警告

iPhone4 5.1
iPhone4s 5.0.1
iPad3 5.1

尝试使用分析器,它将向您展示您正在泄漏对象的确切位置。 - Leena
1
嗨Leena。如问题所述,我没有泄漏内存。我已运行分析器并通过内存分析器运行了一遍。我的应用程序只是使用大量内存来渲染许多视图和几个图像。当收到内存警告时,它会愉快地释放该内存,在iPad上很好运行,但在某些情况下在iPhone上不行。 - Greg G
4个回答

2

在过去的一周中,我一直在解决类似的问题。我正在处理图片方面的不同问题,但也有些相关。

你没有说这些图片都存储在哪里 - 希望你将它们写入文件系统,然后使用[UIImage imageWithContentsOfFile](或者如果使用CGImageRefs,则使用CGImageSourceCreateWithURL)将它们加载到视图中。你需要避免的是将这些图片保存在内存中(iOS中不会进行交换!)。

在我的情况下,我有一些mmap内存来保存这些图片,我甚至卸载了这些内存(这将其同步到文件系统),但由于同步需要很长时间,我一直被“收取”未同步内存的费用。我的做法是对每个文件调用fcntl(fd, F_FULLSYNC)来强制系统在继续之前刷新每个块。


1

我正在开发一个在 iPad 3 上使用了大量大图的应用。

如果将 iOS 5.0 设置为部署目标,当应用程序消耗过多内存时,applicationDidReceiveMemoryWarning 不会被调用,应用程序会崩溃。

但是,如果将 iOS 5.1 设置为部署目标,applicationDidReceiveMemoryWarning 将会被调用。因此,操作系统会刷新先前加载的包含图片的缓存,应用程序就不会崩溃。

主要问题是我使用 UIImage imageNamed: 加载我的图片,如果您的图片很大,请改用 UIImage imageWithContentsOfFile,这样它们就不会被缓存(如果 @2x 的大小非常大,这可能会成为问题)。

请注意,如果我快速显示许多图像,则 applicationDidReceiveMemoryWarning 在 iOS 5.1 中无法及时调用,导致应用程序崩溃!


你好,请问“快速展示多张图片”具体指什么?我想了解一下,以便与我的应用程序在浏览多张缩略图和单张图片时退出的方式进行比较。 - Steve Cotner

0

你可以尝试在Instruments中运行“时间分析器”工具吗?它会告诉你是否在不同的线程中受到CPU限制(虽然除非你自己创建它们,否则我会感到惊讶)。如果这不能揭示问题,还可以运行“分配”工具。


嗨,Scott。感谢你的提示。但愿事情能那么简单。我通过时间分析器运行了它,没有线程占用CPU。当应用程序不做任何操作时,CPU使用率是不存在的,直到它耗尽内存。我还检查了分配情况,没有发现明显问题。在内存耗尽之前,大部分内存都是脏(89%),其中大部分被CoreAnimation占用。还有其他我应该寻找的吗?谢谢。 - Greg G

0

我在运行iOS 5.1的iPad 3上发现了与应用程序DidReceiveMemoryWarning不被调用以及UIApplicationDidReceiveMemoryWarningNotification的NSNotifications相同的行为。我还在其他设备上测试了完全相同的代码,因此您可以将它们添加到列表中:

适当的低内存警告

iPad 2 5.0.1
iPad 2 4.3.5
iPhone 3GS 5.0.1

没有低内存警告

iPad 3 5.1

模式可能是:运行5.0.1-5.1的512 MB或1 GB内存的iOS设备。

我在这个应用程序中没有进行任何重量级UIImage处理。似乎操作系统的行为已经改变 - 要么它有意更积极地杀死应用程序(例如,试图更聪明地杀死看起来具有过于繁重内存使用的应用程序),要么低内存通知只是出了问题。


类似的问题。应用程序崩溃。iPad 2,5.1.1:这里没有内存警告。 我可以在控制台日志中看到CoreAnimation无法分配内存-仍然没有通知。 - Krumelur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接