"no ivar" on Xcode Instruments Leaks Cycles graph - ios

I am using instruments to check my app for leaks and I am trying to learn how to read the leaks cycles data.
I am getting this graph on one of my leaks:
What is the meaning if the graph ? What does it mean "no ivar"?

The "no ivar" message is similar to looking at the call stack of a program that has its symbols stripped. If you were looking at the call stack, you would see a memory address instead of the function name. In your example Instruments is showing the addresses, +16 and +24. Instruments can't find the variable name that allocated the memory so you get the [no ivar] message.
I don't have a solution to get Instruments to provide better information. I've never been able to get Instruments to do much with leak cycles.
UPDATE
If you're trying to find where your code leaks memory, I recommend switching to the call tree view, which you can do from the jump bar. Selecting the Invert Call Tree and Hide System Libraries checkboxes make it easier to locate your code in the call tree view. The checkboxes are on the left side of the trace document window.

Related

How to remove Core Data Object from memory? [duplicate]

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.

Using instruments to find memory leaks

I've tried to read almost every decent tutorial in the internet, but still can't understand what is really happening here:
I've "Hide System Libraries" and "Invert the call tree", but I do not understand how to find actual code responsible for for example this leak. Any tips are appreciated. May be I am missing something obvious. I am getting hundreds of leaks, however I am using weak in closures, I do not have classes referencing each other etc. But it looks like I am missing something fundamental.
The problem shown in your screenshot is Instruments can't find your app's debug symbols. Instruments is showing memory addresses instead of function names. You are not going to be able to find the source of your memory leaks in Instruments without function names, even if you invert the call tree and hide system libraries.
Make sure your project is generating debug symbols. Check that the Generate Debug Symbols build setting is set to Yes. If your project is generating debug symbols, Instruments may be unable to find the dSYM file that contains the debug symbols. In Instruments choose Instrument > Call Tree > Locate dSYM. The dSYM is usually in the same directory as the release version's application bundle. The following article has additional information:
Instruments: Locating dSYM Files
Memory leaks can be difficult to track down. This is likely going to be a time consuming process, so be prepared. In the end, there is usually a lot of trial and error with debugging memory leaks. The "Memory Leaks" instrument has actually only detected one leak for me in the past. I've always had to track them down myself using the "Allocations" instrument.
One of the things that has helped me in the past is to start by trying to figure out what objects are actually being leaked. Click on the allocations instrument (the row above "Leak Checks"). Now try sorting by number of objects released or amount of memory used. See if there are any objects that have a count of 0 released when they shouldn't be sticking around. See if there is an object type that is taking an abnormal amount of memory.
Memory leaks are always due to developer mistakes with memory management. There are some minor memory leaks that exist in some of the lower level private APIs in Foundation and UIKit. At those lower levels, they are dealing with a lot more manual memory management, so its much easier to make tiny mistakes. You can't really do anything about those, but they are relatively rare.
If your application is working just fine, you may not need to worry about fixing these. There is some cost benefit analysis you want to do here. If this isn't impacting performance or stability, is the time investment in fixing these right now worth the minor benefits it will provide you and your users?
However it is worth nothing that memory leaks can add up, so if a user has your app open for a long time, the amount of leaked memory will eventually become a problem if you continue to leak more objects over time. At some point the application will crash and the user will have to re-open. But if your memory leaks are small enough that this doesn't become an issue unless the app has been open for HOURS, is it really that much of a problem anyways? That's always a judgment call on your part.

How to debug memory leaks when Leaks instrument does not show them?

I have an iOS app written in Swift that is leaking memory - in certain situation some objects should be released but they are not. I have learnt about the issue by simply adding deinit debug messages like this:
deinit {
println("DEINIT: KeysProvider released")
}
So, the deinit message should be present in console after such events that should cause the object to release. However, for some of the objects that should be released, the message is missing. Still, Leaks Developer Tool does not show any leaks. How do I solve such situation?
In Xcode 8, you can click on the "Debug Memory Graph" button, in the debug toolbar (shown at the bottom of the screen):
See Apple’s Diagnosing and Resolving Bugs in Your Running App: Visualize and Diagnose Increasing Memory Usage.
Just identify the object in the left panel that you think should have been deallocated, and it will show you the object graph (shown in the main canvas, above). This is very useful in quickly identifying where the strong references were established on the object in question. From here, you can start your research, diagnosing why those strong references were not resolved (e.g. if the object in question has a strong reference from something else that should have been deallocated, look at that object's graph, too, and you may find the issue (e.g. strong reference cycles, repeating timers, etc.).
Notice, that in the right panel, I'm seeing the call tree. I got that by turning on the "malloc stack" logging option in the scheme settings:
Anyway, having done that, one can then click on the arrow next to the relevant method call shown in the stack trace in the right panel of the first screen snapshot above, and you can see where that strong reference was originally established:
The traditional Instruments technique (especially useful if using older versions of Xcode) is described below, in my original answer.
I would suggest using Instruments' "Allocations" tool with the "Record Reference Counts" feature:
You can then run the app in Instruments and then search for your class that you know is leaking and drill in by clicking on the arrow:
You can then drill into the details and look at the stack trace using the "Extended Details" panel on the right:
In that "Extended Details" panel, focus on your code in black rather than the system calls in gray. Anyway, from the "Extended Details" panel, you can then drill into your source code, right in Instruments::
For more information and demonstrations in using Instruments to track down memory problems, please refer to:
WWDC 2021 video Detect and diagnose memory issues
WWDC 2019 video Getting Started with Instruments
WWDC 2018 video iOS Memory Deep Dive
WWDC 2013 video Fixing Memory Issues
WWDC 2012 video iOS App Performance: Memory
Use instruments to check for leaks and memory loss due to retained but not leaked memory. The latter is unused memory that is still pointed to. 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.

app works fine on iPad 2, crashes on iPad 3, with low memory warning

as the title says, I have an app which works on iPad 2, but crashes on iPad 3. when running it the console gives me a low memory warning message. When the crash happens I symbolicate it, but there's really nothing that I can relate to the code, like it shows
process name, UUID, rpages, recent_max, [reason] (state)
and under those column headers just hexadecimal stuff, nothing showing method calls or lines in the project.
Any ideas? am I missing some flags in the code that allows for a better crash log?
Thanks.
If you're getting low memory warnings and fail to release enough memory to resolve the issue, your app will almost certainly crash. The thing is, I don't think that the particulars of how or why it crashed can possibly be illuminating. At that point, you're evaluating secondary symptoms. You really need to go back and figure out why you got the low memory warning in the first place and fix that problem.
As Daniel said, you can look at Technical Note 2151, but as it says:
When you see a low memory crash, rather than be concerned about what part of your code was executing at the time of termination, you should investigate your memory usage patterns and your responses to low memory warnings. Memory Allocations Help lists detailed steps on how to use the Leaks Instrument to discover memory leaks, and how to use the Allocations Instrument's Mark Heap feature to avoid abandoned memory. Memory Usage Performance Guidelines discusses the proper ways to respond to low-memory notifications as well as many tips for using memory effectively. It is also recommended that you check out the WWDC 2010 session, Advanced Memory Analysis with Instruments.
So, a couple of thoughts:
Have you looked for leaks? The Finding Leaks article walks you through how to use instruments to find your leaks.
If you turned on zombies, have you turned them off? Zombies is a great diagnostic tool, but just consumes memory.
Have you run your code through the static analyzer (shift+command+B or select "Analyze" on the "Product" menu)? Especially if using non-ARC code, this can find lots of memory issues.
Have you examined your allocations for unexplained increases without offsetting decreases with the Instrument's Allocations tool. Using that, you can run the program, look at the consumption of memory on the graph and see if you see any increases that aren't offset at some point by the corresponding decreases. And if so, highlight those increases in the graph:
For example, when running the Allocations tool, hold down the option key and then click-and-drag with your mouse to highlight a portion of the timeline, to identify what you want to inspect. You probably want to focus on one of your spikes in allocations. For example, I found a bump in my allocations and highlighted it as such (this was a ludicrously simple example where I create a huge array in viewDidLoad, but hopefully it give you the idea):
Note, I find it useful to show the call tree in the lower panel, it's often useful to select "Hide System Libraries", to focus on your code (and "Invert Call Tree", too). And if you double click on the method name in Instruments (in my example, here, it would be viewDidLoad), Instruments will then show you your code that's doing the allocation:
Low memory warnings generate a different kind of log than standard crashes. Take a look at the "Understanding Low Memory Reports" section of this article to understand what happened with your application and how you can debug it using Instruments: http://developer.apple.com/library/ios/#technotes/tn2151/_index.html

Using Xcode Instruments to print objects from memory address

Is it possible to get more meaningful information on a leaking object in instruments? At the moment Instruments will tell me the type (NSArray) and the memory address (0x123456). Normally if I was debugging with LLDB I'd do a po 0x123456 to get a bit more info on the instance of the object. Is there any equivalent in Instruments, or am I approaching this in the wrong way? Any advice would very welcome!
In the leaks, call tree you can see all the leaks you have, double clicking on any of them will show you the segment of code that is producing it, it also adds a percentage on the line it thinks its doing the leak
Also you can add NSLogs in your code and in instruments navigate to console view to see the logs

Resources