I'm using Instruments with the Allocations instrument. I'm testing only a fixed interaction with my app.
I have a navigation controller which goes 4 stages deep. The first two stages are standard table view controllers and the last two are custom controllers with dynamically loaded images.
So I run my app in instruments (via Run with Performance Tool -> Allocations) and do the following interactions:
1. App Loads
2. I wait a bit until allocations graph stabilizes
3. I tap/push into my navigation controller until the deepest level.
4. I wait for the images to load and for the allocations graph to stabilize.
5. I tap back out of the navigation controller until I'm back to the root level.
6. I wait for the allocations graph to stabilize.
7. GOTO 3.
Now what I've noticed is that between each iteration from 3 to 7 the allocations graph shows a slightly higher value. So the overall allocations are increasing even though I'm doing the same thing and all the view controller's deallocs are being called.
So the timeline looks roughly like this:
1. Start: 1mb
2. Push controllers/Load images: 4mb
3. Pop controllers: 1.1mb
4. Push controllers/Load images: 4.1mb
5. Pop controllers: 1.2mb
6. ... etc ... (always increasing slightly)
So my question is does this mean I have a leak or is this normal? Also what does the allocations graph data actually represent? And why is the value increasing even though I'm popping back out to the initial state? I'm worried that if my app runs long enough it will consume too much memory even though all the user is doing is pushing and popping view controllers.
Any thoughts would be helpful.
Is this in the simulator, or on the device?
As it's good to verify a problem exists on the device, as some system libraries release memory more often on the device than in the simulator.
If Leaks shows nothing, it's because you are still holding a reference to memory somewhere even if you don't think you are. To help track that down, highlight a small portion of the graph where the memory is increasing, and select "created and still living". Now you can see just the memory allocated, and start to track down just where the issue is.
If you have the newest iPhone SDK, the version of Instruments it comes with (2.7 I believe) has a HeapShot feature. You can watch some of the WWDC '10 videos for more information, but essentially you take a shot the first time you pop controllers and then again when you pop a second time. It will show you any memory allocations that are different at the two moments.
You probably have a leak. Check the leaks instrument which can help you find them.
Yes, this is a leak. One of your view controllers along the line is missing something.
If you are loading images then there is a good chance you are using [UIImage imageNamed:] that causes the system to cache and may be a cause of your memory use. But in short yes, you have a leak.
Related
I have two views in my ipad app: one displays a list of records and the other displays the detailed record (including a photo and some text).
When user swipes left/right in the detail view, the root view controller will destroy the detail view controller and create a new one for the next/previous photo.
When I use the allocation profiling, my heap mem is always increasing as I browse through the photos.
I release all the UI controls in my detail view's dealloc method, though I am not sure if it's necessary to release the UIImageView and UILabels from XIB file.
And I used the leak profiling and didn't find any leak while I browse along.
Even after I have looped back all the photos, it will still increase when I destroy & create detailed view controller.
If it's not a leak, what's happening?
Thanks
Leo
Since your question is very generic, and you haven't provided any code I can only recommend you to take a look at WWDC's Session 311 - Advanced Memory Analysis with Instruments video, which gives a good primer on finding (and fixing) various memory related problems.
Try with running with Instruments.
In your xcode run-> Run with Performance Tool-> Leaks.
This will show the Memory Leaks in the application.
I tried to profile an app with Instruments to see how much memory the app is using and whether there are some leaks.
After tweaking it a little bit, I got rid of a couple of leaks and now it's not showing any. However, I noticed that every time I push some view controller and pop it back, the memory goes up, then a little bit down, but not to the level before the push, e.g. Live Bytes showing
1.8 MB before the push
2.1 MB after the push
2.0 MB after the pop
2.1 MB after second push
The funny thing is, after pushing it second time (or even 10 times) it doesn't increase over the previous value, so although it looks like a leak, it's probably some kind of a cache or something. I first thought it's something specific to my code but then I was able to reproduce it pretty much with any view controller, no matter how simple the content happens to be.
Is there a reasonable explanation for this phenomenon or am I just doing something completely wrong in all the examples that I have built ?
Thats happens b/c of autorelease pools, and memory that is suppose to be released for you. It stays for as long as it needs. When you push more viewControllers on the stack more autoreleased objects are created. Some of them will be released earlier the others, but it will very in time, so your memory fluctuation is normal.
I have been hunting down memory leaks for some time in my app. As of right now, as I flip back and forth between two views while watching the memory monitor instrument, the real memory fluctuates between 5 and 6 megs. This is all fine -- as far as I can tell everything is getting released properly when I pop back off a view. However, the virtual memory continues to increase and my available real memory drops rapidly every time I push the view back onto the view stack (even though the real memory usage of the app isn't increasing). Eventually, this all leads to an out of memory crash. Is this a telltale sign of any specific issue, or am I just missing a memory leak somewhere?
EDIT: The odd part is, I get an out of memory crash while the app is still only using up about 5 megs of real memory.
Do not use -retainCount.
The absolute retain count of an object is meaningless. It is an implementation detail. It may be influenced by many factors well beyond your code.
You should call release exactly same number of times that you caused the object to be retained. No less (unless you like leaks) and, certainly, no more (unless you like crashes).
See the Memory Management Guidelines for full details.
In this specific case, you are leaking memory but in a way that leaks can't find it. The objects that are leaked are still connected to your overall application's object graph somehow. Maybe through a notification, maybe through delegation, doesn't matter -- leaks sees the reference and concludes that the object might still be live.
Use the Allocations Instrument. Configure it to only track live allocations (since you don't care about objects that have been deallocated). Do some stuff with your app. Check out what Allocations knows about and explain why all those objects should stick around. You can use the data mining facilities to filter down to just your objects.
Anyway, you can also use the "Build -> Build and analyze" option to find suspicious non-conventional code.
Another reason why you may have memory lost in lower API layers is if you don't remove all your views from your view hierarchy (aka : not calling [view removeFromSuperview] everywhere). At least that's what seemed to have happened to me.
Note that most of time this isn't required, as you would simply release the main view and all its subviews, then rebuild it from the view controller when needed. Things start to get more tricky when you're not releasing the whole hierarchy but instead simply remove some of them from the hierarchy.
In that case, I came to the conclusion that you may have buffers or layers still cached in lower API parts, and in that case your Allocation instrument won't help you.
In order to monitor correctly you'll need to use the "Memory Monitor" (in System). You'll see that the "Physical Memory Free" line dropping close to 0 is the most reliable indicator that a Memory Warning will be issued.
Another advantage of using this instrument, is that you can attach it to a running process, thus making it possible to have console output and instrument running together easily.
Circular references also won't be counted in Leaks but you can track those in Allocations. Best bet is to fire up Allocations and get to a state where you think everything should be gone (or certain objects should be). If they're hanging around go dive in to them and look at where they've been retained and sort out the proper memory ownership/releasing.
As for Allocations, there are some things that it doesn't track that can affect the overall memory. Some of the things include some CGImage backing stores, some CoreAnimation stuff and some database stuff.
Have you used the "Leaks" Performance Tool? And check out the logs in Organizer to see if there's anything there.
Also look into the dealloc for the view controllers and make sure you are properly releasing all of it's objects?
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.
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.
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.
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
My GUI for an iPhone app uses numerous UIViews. The user "flips" through these views when they tap a button to go forward or backward. The views are stored offscreen and are added to an actual view only when the program needs to display it.
During the flip process, the program tells the parent view (a uiscrollview) to remove any existing subview using the removeFromSuperView method, and then adds the new subview, which is the new page that the user should see.
However, after several repeats of this process on the device, the program crashes with gdb exit status 101, which I found is caused by an out of memory error.
I tried diagnosing this problem using the Leaks tool, but to no avail. There is only 1 or 2 small memory leaks and the total mem usage on the device by the program is only 2.5 mb. Is it possible that video memory, not system memory, is running low?
I came across this post regarding backgroundColor and mem usage, but I need further explanation. Should I reduce setting the backgroundColor to prevent the UIView's CALayer from hogging too much memory?
Do you have access to the iphone sample code on apple? Sounds like the PageControl Sample Code program is a good example of what you're looking for. And the sample code programs don't have memory leaks or any such problem :) Link here
When you were using instruments, did you check the ObjectAllocations? I've found that to be more useful than the leaks tool (object allocations is one of the tools leaks includes though). I would think that if video memory were running out it would be a different error, but I could be wrong.
Where are you storing all these views? Specifically, do you have some array (NSArray) that has these views when you flip through them?
The views won't get deallocated unless their reference count goes to zero. Your `[[UIView alloc] init] makes the reference count at 1, adding it as a subview makes it 2, and removing it from a subview makes it 1 again. Seeing as you don't get told of a specific leak, it seems that you're not really leaking as much as storing it somewhere.