Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS app runs out of memory without receiving a low memory warning

I have an existing app that I made some recent changes to and I have been testing those changes. The app works perfectly fine on every iPad I test it on (iOS 4 and iOS 5). After loading several (50+) image-heavy views in my app I get a low memory warning and my viewDidUnload methods get called and they properly nil out all of their controls and my in-memory image cache clears itself out and the app continues just fine.

However, on an iPhone 4 and iPhone4s (iOS 5.0.1 and iOS 5.1) I run into a problem where my application runs out of memory without ever receiving a low memory warning. After loading several different views, eventually a new view will come up and be mostly blank and on the console I see memory allocation messages and the whole phone becomes un-responsive and sometimes kills my app.

The particular view that this happens on is different every time, so it's not related to any one view, just the accumulation of memory over time. I have also confirmed that I don't have any memory leaks either.

This existing question is similar:

IOS app killed for Low Memory but no Memory Warning received

and that answer suggests that this could happen if I'm stuck in a loop, but I'm pretty sure that my code isn't stuck in any loops. I'm just clicking through from one view to another in a UINavigationController and several images load in each view. Also, the other question was specifically happening on an iPad where I'm not seeing this issue on an iPad, only iPhones.

BTW, I've tried registering for the low memory notification through NotificationCenter and have an applicationDidReceiveMemoryWarning method in my app delegate and have breakpoints at both and neither get called. Also, no low memory message shows up in the debugger console either.

Any ideas on what might be happening?


Added on 3/26/2012:

Interestingly enough, when I tested my app on the new iPad, it has this same problem that I'm seeing on the iPhone 4 and 4s where the low memory notification is not being received. So I'm wondering if I'm seeing the same problem as this other thread:

The New iPad: Low Memory Warnings Not Appearing?

but that the developer on that thread is testing an iPad-only app and therefore not testing and finding this same problem on any iPhones.

I have done some extensive testing and have a list of devices where I properly received the low memory warning and devices where I don't ever receive it. So far I only see the problem on iOS5 or greater, however on iPad1s with iOS 5.0 and 5.1 I don't see the issue, so it's not just a problem on all devices on iOS 5.

Here is that list:

Proper Low Memory Warning

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

No Low Memory Warning

iPhone4 5.1
iPhone4s 5.0.1
iPad3 5.1
like image 271
Greg G Avatar asked Mar 24 '12 00:03

Greg G


2 Answers

I've been banging my head on similar problems for the past week. I'm doing something different but with images so somewhat related.

You don't say where all those images are located - hopefully you write them to the file system, then load them into views using [UIImage imageWithContentsOfFile] (or if using CGImageRefs, then use a CGImageSourceCreateWithURL). What you want to avoid is having the images in memory (no swapping in iOS!).

in my case I had some mmap memory to hold the images, I had even unmapped the memory (which syncs it to the file system), but since syncing takes so long, I was being "charged" for that unsynced memory. What I did was essentially call fcntl(fd, F_FULLSYNC) on each of these files to force the system to flush each block before I continued.

like image 139
David H Avatar answered Sep 28 '22 12:09

David H


I'm working on an app with tons of big images, on an iPad 3.

If I set iOS 5.0 as the Deployment Target, applicationDidReceiveMemoryWarning does not get called if the app consumes too much memory, and the app crashes.

However, applicationDidReceiveMemoryWarning does get called if I set iOS 5.1 as the Deployment Target. The OS thus flushes the cache containing the images that were previously loaded and the app doesn't crash.

The main problem is that I use UIImage imageNamed: to load my images, if your images are big use UIImage imageWithContentsOfFile instead so that they don't get cached (which is an issue if the size of the @2x is very big).

Note that if I display many images very quickly, applicationDidReceiveMemoryWarning doesn't get called in time in iOS 5.1, and I crash!

like image 42
Eric Avatar answered Sep 28 '22 12:09

Eric