I recently watched one of the WWDC 2010 videos: Session 311 - Advanced Memory Analysis with Instruments. The link is here.
There is an interesting example in the video on finding Abandoned Memory. They say that it is often more important to debug than leaks but can be more difficult.
Abandoned Memory is defined as "Accessible allocated memory that is never used again".
A leak is defined as "Allocated memory that can no longer be reached."
The primary way to find Abandoned Memory is to take heap shots using the Allocations instrument.
However, after determining that I have abandoned memory in my code, I have found that it is really difficult to find out exactly where it is coming from.
I am looking for some good tips or resources for finding Abandoned Memory.
Thanks!
In Instruments, you can get a call stack for any object identified by a heapshot. Screenshot:
So what we've got here is a contrived case where I allocate a 1MB NSMutableData everytime the user taps a button. In the center-bottom pane, I've got 4 heapshots, and I have one expanded to show the objects that were created but not released since the last heapshot. I've highlighted a 1.25MB "non-object" allocation, and in the right pane, it shows me the exact call stack where this allocation occurred. One trick about that panel on the right is the slider along the bottom -- it controls the elimination of stack frames. If you want to see all the stack frames, drag it all the way to the right. Grayed out frames are those for which you don't have source code, and non-grayed-out frames are your code (or code you have both symbols and source for.) (Also, if you're not seeing the panel on the right, check the "View" buttons in the toolbar.) What other information are you looking for?
To summarize bbum's excellent blog post:
Profile your app using Instruments
Use the Allocations template
When the app isn't running, click the little i next to the Allocations track header and check Record reference counts; this will let you know where the items are being retained, not just where they are allocated.
Run your app, do something, then return to a default state. For example, open a new document window, then close it.
Click the "Mark Heap" button in Instruments.
Repeat steps 4 and 5 several times.
When you review the allocations in Instruments, you can click the right-arrow button to see a history of events for that instance, including all places it was allocated, retained, released, and autoreleased.
Related
Is there a tool or method to locate strong references cycles in my SWIFT code?
A strong reference cycle is when two instances of classes reference each other without the proper safeties (weak/unowned) hence preventing the garbage collector from disposing of them once all the variables I created stopped referencing those objects.
The method for finding strong reference cycles is the same in Swift as in Objective-C.
You'd run the app from Xcode, exercise the app sufficiently to manifest the cycle, and then tap on the "debug memory graph" button (). You can then select an unreleased object in the panel on the left, and it will show you the memory graph, often which can clearly illustrate the strong reference cycles:
Sometimes the memory cycles are not as obvious as that, but you can at least see what object is keeping a strong reference to the object in question. If necessary, you can then track backward and identify what's keeping a strong reference to that, and so on.
Sometimes knowing what sort of object is keeping the strong reference is insufficient, and you really want to know where in your code that strong reference was established. The "malloc stack" option, as shown in https://stackoverflow.com/a/30993476/1271826, can be used to identify what the call stack was when this strong reference was established (often letting you identify the precise line of code where these strong references were established). For more information, see WWDC 2016 video Visual Debugging with Xcode.
You can also use Instruments to identify leaked object. Just run the app through Instruments with the Allocations tool, repeatedly (not just once or twice) returning the app back to some steady-state condition, and if memory continues to go up, then you likely have a strong reference cycle. You can use the Allocations tool to identify what type of objects are not being released, use "record reference count" feature to determine precisely where these strong references were established, etc.
See WWDC 2013 video Fixing Memory Issues and WWDC 2012 video iOS App Performance: Memory for introductions to identifying and resolving memory issues. The basic techniques proposed there are still applicable today (though the UI of Instruments tools has changed a bit ... if you want an introduction to the slightly changed UI, see WWDC 2014 video Improving Your App with Instruments).
As an aside, "garbage collection" refers to a very different memory system and isn't applicable here.
You can add deinit functions to your classes that will get called when your objects are deallocated.
If deinit isn't getting called, while your app is running, you can press the Debug Memory Graph button (circled below) and inspect what has a reference to what.
Use the dropdown menus at the top of the middle pane to toggle between classes and instances of classes.
If something is getting allocated over and over again without getting released you should see multiple instances, and you should be able to see via the directional graph if one of its children is holding a strong reference to its parent.
Use instruments to check for leaks and memory loss. Use Mark Generation (Heapshot) in the Allocations instrument on Instruments.
For HowTo use Heapshot to find memory creap, see: bbum blog
Basically the method is to run Instruments allocate tool, take a heapshot, run an iteration of your code and take another heapshot repeating 3 or 4 times. This will indicate memory that is allocated and not released during the iterations.
To figure out the results disclose to see the individual allocations.
If you need to see where retains, releases and autoreleases occur for an object use instruments:
Run in instruments, in Allocations set "Record reference counts" on (For Xcode 5 and lower you have to stop recording to set the option). Cause the app to run, stop recording, drill down and you will be able to see where all retains, releases and autoreleases occurred.
very simple approach is to put a print in deinitialiser
deinit {
print("<yourviewcontroller> destroyed.")
}
ensure that you are seeing this line getting printed on the console. put deinit in all your viewcontrollers. in case if you were not able to see for particular viewcontroller, means that their is a reference cycle.possible causes are delegate being strong, closures capturing the self,timers not invaidated,etc.
You can use Instruments to do that. As the last paragraph of this article states:
Once Instruments opens, you should start your application and do some interactions, specially in the areas or view controllers you want to test. Any detected leak will appear as a red line in the “Leaks” section. The assistant view includes an area where Instruments will show you the stack trace involved in the leak, giving you insights of where the problem could be and even allowing you to navigate directly to the offending code.
I am using Instruments to find memory leaks in my app.
When a object alloc, a blue block(line) display in Instrument, like this:
Screenshot of Instruments's timeline, showing the Allocations graph http://naituw.com/temp/instruments.png
When the object have been release, the blue line will disappear.
But when I make some operation in my application, some blue block left there, doesn't disappear, How can I know what those block actually is in the memory? Thanks!
Select the instrument and look in the list in the lower half of the window. It will show a table or outline (depending on the instrument) listing what the instrument recorded.
For the Allocations instrument, it lists things your application has allocated. Depending on the view settings, they may be objects that are still alive or all objects, even those that you have freed.
For the Leaks instrument, it lists things your application has allocated and leaked (i.e., no longer has any reference to). Note that you might still be wasting ever-increasing amounts of memory on things you will never use, not because you don't have a reference to it but because it's in a write-only cache (you stash it but never look it up) or similar situation. Bill Bumgarner calls this “abandoned memory”.
With either instrument, you can click on ➲ buttons within the list to drill deeper down into it, to see the list of allocations of a given type (e.g., all NSImages) or everything that happened to a single object, from birth to death. The latter is extremely useful for hunting down both leaks and over-release crashes, and is the reason why Instruments's Zombies template is so much better than NSZombieEnabled.
In leaks instrument these shows the memory allocations that took place at the particular time.
i m facing big problem with system libraries allocations.
i didn't get any leaks from my application still so much allocations.i attached various screen shoots. in my application using custom picker which get all images from assert library.which are pick from picker showing images on scroll view.
its screen shot when my app with 35 images on scroll view.if again i pick images from custom picker allocation increased.i am seeing object details its all related to frame Work allocations.not from my application
see the allocation object list response library is DYLD.
its my leaks screen shot
how can we release these allocations? please help me out ?
Just because you have no leaks doesn’t mean you are managing memory correctly. What you have is what I call memory bloat — you are retaining it longer than you need to. (A leak is allocated memory with no references. Bloat is allocated memory that has a reference but should have none.)
http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/ will give you some good strategies for using Instruments to find them. (This is a very credible source, so far as I know he still works at Apple.)
make sure your application has no leaked objects and they will also disappear in instruments. For sure its pointing to a system library but it is always a result of your bugs. Select one of them and open the right view. Probably it will show you the right code stack and the allocated line of code.
The other thing you can do: run the static analyzer Product->Analyze it will find all (at least most) your leaks ;)
Please help me understand how can i use this statics shown in image.
How can i use heapshot effectively to detect memory leaks?
I have added image of Instrument using leaks.but i am unable to find exact location of memory leak.
Please guide me for this.
Basically a heapshot in this screenshot will display any objects that were created after the previous snapshot and that are still 'live' (have a retain count > 0).
The typical usage would be to hit "Mark Heap", then navigate into a view controller, tap a few buttons, perform a few actions, and then hit the 'back' button. Take another snapshot and examine the list of objects. You should make sure that there aren't any objects hanging around that should have been cleaned up. This may be things like the view controller itself, model objects, etc.
If you want to detect real leaks (unreferenced objects) use the Leaks tool. If you want to find other types of unbounded memory growth, i.e. objects that are still referenced and alive which shouldn't be, examine heapshots using the allocations tool like in this screenshot.
EDIT:
You added a Leaks screenshot to your original post. To see the stacktrace for where this object was allocated, click this button:
This should show you where the object was created. Then you need to figure out where the appropriate release call needs to go.
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