Dealing with strong reference cycles in Xcode 6.4 - ios

Recently, I’ve received a quite large and ugly legacy code written in Swift 1.2 with full of singletones and managers referencing to each other. One of my task is to clean this up and get to the point of initial home screen - when all managers, views, singletones are stopped and nil’ed.
My current approach for tracking leaks was simple. In every meaningful classes I was counting instancesCount, a static variable which was incremented in init and reduced on deinitialization process. Of course, in XXI century with those all mature tools, its not smart idea for finding allocation leaks but... I don’t know why, Xcode instruments wasn’t very helpful. They were indicating troubles where everything was fine according to my approach. For example, instruments were saying that one of my manager is never deinitialized - which was not true, as instanceCount was 0 for this particular manager in the initial home screen. Weird.
Anyway, all this could close up with question: how to detect why my instance couldn’t be deinitialized and who keeps reference to it?
Reading code line by line and finding places of retain cycles is pointless as codebase is very complex and time - like always - is limited.

Use Instruments with Allocations Trace Template. It tracks reference count changes for each object and shows when it was increased and when it was decreased. No need for manual monitoring here.

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.

Xcode/Swift - Cannot resolve memory issues with Instruments

My application has memory issues where after a certain threshold, the application will crash.
I've been instructed to use Instruments and select the Allocation option.
However, I can never seem to get a "direct" answer to my issue, I have attached screenshots below to help describe the issue better.
The memory issues are not linked to any ViewControllers or files that I have created. Rather other libraries/frameworks which I had no idea were being used. I have been battling this issue for a few weeks, I have altered my code/implemented a variety of methods which I believed may have resolved the issue. However, no luck.
Could someone please tell me how I can combat this issue? As I cannot seem to force the memory to be released which in turn means I have this giant memory bug within my application.
Thank you.
Edit - Added a screenshot of the memory usage when viewing an image at full resolution and returning to the home screen.
A couple of thoughts:
See this answer which talks about using “Debug Memory Graph” tool featured in WWDC 2016 video Visual Debugging with Xcode. That tool is often easier to find issues than Instruments. It organizes the reference counting types by target/framework, making it much easier to sift through the results.
But if you’re dealing with non-reference counted malloced data, then Instruments is the way to go, with all the complexity that entails. But “Debug Memory Graph” is often a better first line of defense.
You said:
The memory issues are not linked to any ViewControllers or files that I have created.
Make absolutely sure that your classes aren’t any buried down there lower in the list. There will be far fewer and the sizes are smaller, so they won’t appear up at the top and they’ll be buried in the list even tho they’re likely to be the root of the problem. Frankly, if your app is running, some of your classes have to be in there somewhere. Lol.
Again, the “Debug Memory Graph” approach helps identify your own objects much more easily than Instruments.
If possible, I’d suggest running the app, returning back to some home screen where you expect stuff to have been released, and repeat that process a few times. The first time you return to a quiescent state is not very illuminating, because there’s going to be a lot of internal caching going on. But the subsequent times you exercise the app and return to that home screen, you’ll have a better example of what’s getting allocated and not released without all of this noise of stuff the OS did on the first iteration:
(Taken from WWDC 2013 Fixing Memory Issues.)
Hopefully, the “warmup” memory isn’t too dramatic, but the red area is what we often focus on, as this is what is “wasted” as we continue to use the app (resulting in eventual crashes).
Unfortunately, your allocations curve isn’t showing it drop at all, which is worrying. Now, maybe you don’t have a “home screen” to which you can return, so maybe this isn’t relevant. But even in that scenario, you should have some state in your app that you can see memory being recovered. It’s hard to say on the basis of the information provided.
You haven’t mentioned it, but confirm what debugging options you have. For example, if you have zombies turned on, you might not see memory drop back as much as it should. Often when we first encounter these sorts of issues, we start flipping on all of these debugging options, but they have an impact on the memory profile of the app. So if you’ve been turning on things like zombies or what have you, you might want to make sure you turn them back off to make sure they’re not part of the behavior you’re seeing.
I’d suggest simulating memory warnings and see if you can see memory being recovered. Make sure your code is observing and responding to memory warnings, purging memory where it can.
This is all general advice and we can’t offer specific counsel without seeing what your code is doing. I’d suggest you create a copy of your project, prune out unrelated stuff, and keep doing that until you have the smallest possible reproducible example of this unbridled memory growth. Often that process will be enough for you to diagnose the problem on your own. But we can’t pour through tons of code. We need a minimal, complete, and verifiable example of the issue.
Bottom line, “Debug Memory Graph” is often our first level of analysis. Run the app, identify what objects you expected to be released but weren’t, and go from there. Also keep an eye on how many of these objects are out there (e.g. if you see the same view controller multiple times, that’s a sign of a strong reference cycle or some circular invocation of view controllers).
Instrument just shows you overview of how your app handling memory/CPU etc. When you find something in instrument, you have to make changes in code.
Refer this: For that you should understand how stong and weak works in iOS.
Once you understand ARC in iOS. You will understand your memory leaks in your code.
Trick is :
Try to check number of objects are not getting removed from memory in instrument.
Then check code for strong reference of object and try to remove unnecessary strong references.
Hope this will help you.
I fixed the issues which I had. Just in case anyone in future experiences the same issues this is what I did:
If declared my outlets/delegates as weak
Wherever I used the keyword self in a block where XCode demanded I use self, I added either [weak self] in or [unowned self] in
Remove any instances of the word self which were not required
Added a deinit and included a print statement
Added a breakpoint where the deinit method is called
Commented out functions in my viewDidLoad method and go through each one to see which one/if one caused the issue.

Instruments: Leaks and Allocations (tvOS)

I’m currently working on a tvOS app. This is my first native (Swift) app. The app will be a digital signage app, used during events or in offices of companies.
One big difference compared to a typical app on iOS/tvOS is that it needs to run pretty much 24/7, so memory is a big topic for this app. The smallest leak will eventually cause the app to crash.
The app is constantly looping through a set of fullscreen slides. At the bottom of the screen there is a ticker with 10 articles (refreshed every 10 seconds - now during development). Below is a screenshot of the weather slide, to get an idea.

Currently the app is crashing after a period of time and I’m pretty sure I’ve narrowed it down to the ticker component (when disabling it, the app lives for days). If I use the ‘Leaks’ preset in Instruments I get the following result:

It looks like it’s leaking Article instances. I’m recreating Article instances every 10 seconds and providing them to the ticker component. I think that is why new instances leak every ~10 seconds.
Before I started using the ‘Leaks’ preset in Instruments, I used the ‘Allocations’ preset, while using this all seemed fine to me. But I’m probably misreading the results…
Using allocations:

The way I read this is that currently 10 Article instances exist in memory, and 31 have existed but are cleaned up now - so I’m safe.
But the app still crashes.
I’ve read a lot on retain cycles, implemented weak/unowned where I believe I should.
So my question is not so much about code, but more about how to read this data, what does a Leak mean in this context, and why do I see these ‘leaks’ not as persistent objects in the Allocations window?
(tests are done on multiple devices + simulator)
If you see a steady (i.e., approximately n GB / minute or hour) increase in memory usage in Instruments, that is a good sign that objects are being created, but not dealloced. Your allusion to weak and unowned vars makes me think that you know this, but you may not have found all sources of your leak. I would suggest taking a few generation summaries in Instruments, and looking at specific classes/objects in Heap allocations. Your problem classes will steadily increase in number, and likely never decrease. Try to debug the problem from there.
As for what 'leak' means in this context, it's what it always means: Your computer is not releasing memory resources. It may seem different, because we are used to thinking of a leak as something that eats through memory at a much faster rate (like an infinite loop running on four cores, or something), but that kind of leak and this are actually the same thing; yours is just slower.
I’m back after weeks trying to figure out what was wrong. The good news, I found my leak, and solved it!
The issue was solved by removing a closure inside another closure keeping a reference to a variable in the first closure. This caused a retain cycle.
I really don’t understand why I didn’t find it earlier, I asked a new question for this here: getting-different-data-in-instruments-based-on-method-of-profiling.

Xcode fix memory problems

It's the first time I have to fix a memory problem from one of my iOS apps, so I'm not really sure how to track it, I've been reading some post from different blogs and I've found that my memory is constantly increasing:
The problem is that I don't know how to track and fix the problems in my code, and I also don't know what should be the best "Growth" in memory. Thank you.
First, I'd recommend watching WWDC 2013 Fixing Memory Problems and WWDC 2012 iOS App Performance: Memory videos. They are dated, yet still relevant, demonstrating of taking the above screen snapshot down to the next level in order to identify the underlying source of the memory issue.
That having been said, I have a couple of observations:
In my experience, nowadays, the problem is rarely "leaked memory" (i.e. memory that has been allocated, for which there are no more references, but you neglected to free it). It's rather hard to leak in Swift (and if you use the static analyzer on Objective-C code, the same it true there, too).
The more common problem is "abandoned memory" resulting from strong reference cycles, repeating timers not getting invalidated, circular references between view controller scenes, etc. These won't be identified by the Leaks tool. Only by digging into the Allocations tool.
First, I often like to see what accounts for the bulk of the abandoned memory. So I double click on a top level call tree and it will show me where the abandoned memory was allocated:
Note, this doesn't tell me why this was abandoned, but by knowing where the bulk of the abandoned memory was allocated, it gives me some clues (in this example, I'm starting to suspect the SecondViewController).
I then drill into the generations results and start by looking for my classes in the allocations (you can also do this by manually selecting a relevant portion of the allocations graph, as discussed here). I then filter the results, searching for my classes here. Sure, this won't always be the most significant allocation, but in my experience this sort of abandoned memory almost always stems from some misuse of my classes:
Again, this is pointing me to that SecondViewController class.
Note, when looking at generations, I generally ignore the first one or two generations because they may have false positives stemming from the app "warming up". I focus on the latter generations (and make sure that I only "mark" a generation when the app has been returned to some-steady, quiescent state.
For the sake of completion, it's worth pointing out that it's sometimes useful running Instruments with the "Record reference counts" feature on the unreleased allocation:
If you do that, you can sometimes drill into the list of retain and release calls and identify who still has the strong reference (focus on unpaired retain/release calls). In this case it's not very useful because there are just too many, but I mention in because sometimes this is useful to diagnose who still has the strong reference:
If you're using Xcode 8, it has a brilliant object graph debugger that cuts through much of this, graphically representing the strong references to the object in question, for example:
From this, the problem jumps out at me, that I not only have the navigation controller maintaining a reference to this view controller, but a timer. This happens to be a repeating timer for which I neglected to invalidate. In this case, that's why this object is not getting deallocated.
In the absence of Xcode 8's object graph debugger, you're left to pouring through the retain and release references (and you can look at where each of those strong references were established and determine if they were properly released) or just looking through my code for things that might be retaining that particular view controller (strong reference cycles, repeating timers, and circular view controller references are the most common problems I see).
Minimizing your app's Memory Footprint
For the benefit of both stability and performance, it's important to understand and heed the differing amounts of memory that are available to your app across the various devices your app supports. Minimizing the memory usage of your app is the best way to ensure it runs at full speed and avoids crashing due to memory depletion in customer instantiations. Furthermore, using the Allocations Instrument to assess large memory allocations within your app can sometimes be a quick exercise that can yield surprising performance gains.
Apple Official Document

App Crashes saying Memory Warning Using Arc [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I am using ARC and the app crashes saying received memory warning. I have used the apple instruments:
It looks like I do not have any leaks but I cannot find where is wrong. The crash has to do with the memory and due arc I cannot use release and any sort. It is my first time dealing with memory usage using arc. Is there away I can Debug this since I am dealing this for nearly two months. I have my code on my git hub so it will be helpful if you look at it. You can find it here.
I am dealing this problem for weeks and want to end this. Thanks.
Not all "leaks" show up in the "Leaks" tool in Instruments. And, notably, if a view controller has a strong reference cycle, not only will the view controller not be deallocated, but none of its members will be deallocated either. But looking at your allocations your memory is never getting released, so you probably do have a leak somewhere. It's hard for us to diagnose, though, because your github project is incomplete. But here are a few thoughts:
Strong reference cycles don't always show up in the Leaks tool.
In a variation of the traditional strong reference cycle, your code employs a repeating NSTimer that will keep a strong reference to your view controller which will result in your view controller never being released (because the timer maintains its own strong reference to your view controller). To fix this, your view controller must stop the timer when the associated view disappears:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.timer = [NSTimer scheduledTimerWithTimeInterval: 0.05f target: self selector: #selector(tick) userInfo: nil repeats: YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.timer invalidate];
self.timer = nil;
}
Besides of strong reference cycles, like above, another phenomenon that can result in increasing allocations like you've shared with us is a circular flow between view controllers. For example, if your app does a push/modal segue from view controller A to view controller B, the app must then pop/dismiss/unwind back to view controller A. If you push/modal from B to a new instance of A, you'll end up abandoning your old instance of A, resulting in an allocations graph like yours.
These are just a few examples of the sorts of things that can result in your allocations graph. But it's hard for us to diagnose further with the limited information provided.
Before doing anything else, use Xcode's static analyzer (command+shift+B or "Analyze" on the "Product" menu) and make sure you get a clean bill of health there. Let Xcode help you identify your programming issues in your code.
Once you've resolved any issues identified by the static analyzer, you can then dive into Instruments. Refer to the WWDC 2012 video, iOS App Performance: Memory. About 32 minutes into it, it shows an allocation graph much like yours, describes the three sources of those sorts of issues (leaks, abandoned memory, or cached memory), and shows you how to use the Allocations tool to identify the precise source of the problem.
You should follow along that video and you'll definitely gain some familiarity with Allocations tool features (such as comparing heap snapshots) to identify what object leaked, or look at the extended details and call tree to find the source code that created the leaked object. Once you identify precisely what's leaking, we can help you resolve the issue.
By the way, even easier than the heapshots described in that video, I'll often just option-click-and-drag at a particular spike (notably one that obviously is never released) in the graph in "Allocations". If you do that, the object summary will show you the objects (most useful if you sort by "Live Bytes") that have been allocated and not released during that window of execution:
That can be helpful, but sometimes it's just cryptic CFString or CGImage allocations. It's therefore sometimes useful to see where in your code those objects were allocated. If you switch from "Statistics" - "Object Summary" to "Call tree", it will now show you how much memory was taken up by each of your methods (and I find this screen most useful if I also check "Invert Call Tree" and "Hide System Libraries"):
If you then double click on a symbol name here, it will actually show you the offending code:
Through that process, I can see what is being allocated at that spike, and I can now go about identifying why that memory is never getting released (in this case, it was my deliberate use of a repeating timer that I never invalidated).
There are other tricks that are useful in more complicated scenarios (I'm particularly fond of having my code signaling flags that appear in instruments so I can more accurately correlate activities in my code with what's going on in Instruments), but that's probably too much to get into here. Hopefully this option-click-and-drag in Instruments will be a useful tool to identify what's being allocated and never released.
There are cases where ARC doesn't work (by design, I mean). When you use CoreFoundation or anything else below the Cocoa level you need to manage your memory as before. Also, you could have retain cycles (most often with blocks). Try analyzing the project (next to Build in Xcode) or running with Instruments
ARC doesn't help if you're just using a lot of memory. It's possible your data set is just too large and you need to refactor to use less memory at a given time
As I have glance you code on github
There is one file name iCarousel.m.make sure it is ARC compatible and if not than go to the Target/Build phases/complie sources and give fno-objc-arc flag to iCarousel.m.
Make all objects nil in viewdidunload method of all classes.
hope it will help you.

Resources