views:

239

answers:

3

I have an application that is being ejected by iPhone OS for "low memory".

I have passed it thru instruments and I see zero leaks, and memory usage is around 640 kb.

The application crashes when I add objects to the screen.

This is how it works. I have a UIImageView based class that is very simple and add a few properties to the objects. This class is used on the created objects.

When the user taps a button a new image of that class is created and added to self.view.

After about 15 objects added, the application is ejected with low memory warning.

Instruments report no significant memory usage. Even after 15 objects added, the ALL ALLOCATIONS entry never goes beyond 660 kb. Each object can be one out of five 120x120 pixels image.

If it is not object allocation or leaks, what can that be? Please tell me what directions should I follow to locate the problem.

Thanks for any help.

A: 

I discovered the problem had nothing to do with my code. Every time I use quartz on the iPhone I have this kind of problem.

Quartz has a serious problem that has to be fixed. As far as I detected, it gets chunks of memory to perform drawing and does not release them even if you release all variables and references you use. Even if you put all variables nil.

Quartz is a memory eater and a source for crashes.

Here is a project I've created to demonstrate how Quartz can crash your project. Look for a method inside inside MyClass.m, called imageWithBorderFromImage. This method uses quartz to draw a dashed border around the object. Run the project and click several times in the button. Every time you click, a new object is added to the screen, on top of the previous one. After about 20 clicks the application is ejected by springboard. Before that you will see LOW MEMORY warning on console.

Before telling me that the problem is too many views created, disable the quartz method and see that the application does not crashes anymore. In fact I was able to click 80 times and was still able to continue clicking, but I stopped the app.

Download the project QuartzNightmare here

Digital Robot
Can you pinpoint any particular calls? On what OS version? I'm not having any Quartz memory problems in my app.
Rhythmic Fistman
I highly doubt that it is a problem with the Quartz drawing system, because Quartz is used for drawing practically every visual element in the OS. I use heavy Quartz drawing in my applications and have never had it be the source of memory leaks that weren't my fault. As I explain in my answer, you may have been leaking memory by not properly releasing Core Foundation objects that you had created for drawing purposes. This may not have shown up as a leak in Instruments.
Brad Larson
I have included a project where you can see the problem.
Digital Robot
Looking at your project, the issue seems to be that you keep adding views to the screen and never remove any of them. If you removed the old views before adding a new one, I bet you would not run into this issue. This is not a Quartz problem, and it's not a memory leak, but you are still consuming a lot of memory with all of these views you are creating.
Brad Larson
*Ok, but try again removing the quartz part of the project and tell me if the application crashes...* I have another application of mine that adds ONE view and uses a similar method of drawing a border and other stuff on that image and it crashes after a while. On that project, the image has 500x500 pixels and quartz generates a memory use of 36 MB of memory. Why quartz is using 38 Mb of memory do draw a line on an image with one megabyte memory use is a mystery. Obviously, it crashes.
Digital Robot
Obviously, if you remove the method that creates an image for display to the screen, you will be using less memory because nothing will be drawn. However, if you replace the Quartz drawing code with a PNG image loaded from disk, you will run into the exact same memory problem, because this has nothing to do with Quartz. You are simply loading too many views onscreen at once and never removing them from display. Each view uses a significant amount of memory to display its content, so you eventually exhaust the available memory for your application.
Brad Larson
Sorry, but you are talking without performing any test. Try this: instead of using the quartz routine to draw a line around the image on a second UIImageView, add a PNG with the dashed line, in a second UIImageview. Now every time you click on the button you add two images. This is how I solved this problem that has no relation to the number of views added to the superview. Please refrain from answering without doing what I am sayingIf you do that, you will see that you will still be able to click 80 times, at least, or more, without crashing. My application never crashed after that.
Digital Robot
additional note: some pinheads are giving me negative points because they cannot stand critics for quartz. I am not saying quartz is a total failure. I am saying that it has problems and the main problem as I see is this memory hungry and not releasing the memory back even when your code is without any leak.
Digital Robot
I tested your code on a device and, as I suspected, building up views that are never removed from their superview is the cause of the memory usage. I fixed your project so that these views are removed when the next one is added: http://www.sunsetlakesoftware.com/sites/default/files/QuartzNightmare-fixed.zip and memory usage stops increasing after the first view is added (it tops out at 5.23 MB on my iPhone). This is with all of your Quartz drawing, clearly indicating that Quartz is not at fault here.
Brad Larson
Thanks for your help but the views are supposed to work like this, the user can add ass many views he wants. I simply disabled quartz and the memory never tops 750 Kb. See the difference? 100 objects added (= 200 images: image plus another one with the dashing) and the app never crashes).
Digital Robot
A: 

Leaks are not your problem. Over-retention is.

Look at Object Allocations. If that graph just rises and rises, your app will be killed. What make the iPhone especially angry is when you are told to let go of some memory (low memory warning) and no memory is freed. Your code may just be an extreme case of this, but you should free up SOMETHING when you get this message.

Kendall Helmstetter Gelner
as I said in my question, my app has no leaks, my memory usage is below 700 kb and yet the app crashes. The guilty was quartz. This time I was able to replace the method with a non-quartz one and the app now is smooth as silk. ALl my apps that use quartz had the same problem. Ah, and I have nothing to free when I receive the memory warning. My app has a small footprint.
Digital Robot
I have included a project where you can see the problem.
Digital Robot
+5  A: 

The ObjectAlloc instrument does not indicate all memory usage within your application. Views and other visual elements do not show their full size in ObjectAlloc, so you will want to use the Memory Monitor instrument to see the actual memory size of your application at any given time.

Also, just because Instruments does not report leaks does not mean they aren't there. Run your application through the Clang Static Analyzer to take another look for potential memory leaks (via Build | Build and Analyze under Xcode 3.2 or by downloading the standalone tool). Again, even if this passes and you still see continually increasing memory consumption you have a leak somewhere.

You mention using Quartz drawing in your comments. You need to remember that Core Foundation objects used in Quartz also follow a specific memory management model, where everything you create with a function having Create in its name must be released using a matching function like CFRelease(). This may not show up as a leak if you forget this, but it is.

Brad Larson
Clang reports ZERO problems.Instruments reports ZERO leaks.Instruments reports memory allocation below 700 kb.Every variable I used in Quartz has a CFRelease.I am telling you. Quartz is the problem. If you guys want I can prepare a project using a very simple quartz function inside a class and you can see by themselves. The problem vanished when I removed the quartz function and the quartz method has no leaks and no errors. I see the problem is a mix of leak (that only Apple can fix) and not released cache memory.
Digital Robot
When you say "Instruments reports memory allocation below 700 kb" is that in the ObjectAlloc or Memory Monitor instrument? As I said, ObjectAlloc does not show the true size of your application and Memory Monitor does. If I remember correctly, even very simple applications tend to use 1.5 - 2 MB of total memory.
Brad Larson
I have included a project where you can see the problem.
Digital Robot