As ARC came into existance in iOS, do we stil need the requirement of using xcode instruments (Allocations and Leak)? - ios

As I learnt from the apple documentation that ,In iOS ARC will automatically take care of the memory leaks and memory management.
But my doubt was, do we still need the role of Xcode instruments (Allocations and Leak) to ensure whether memory leak has happened in our application??
Please do share if you know the solution.

Yes, of course you need to use Intruments.
Swift uses Automatic Reference Counting (ARC) to track and manage your app’s memory usage. In most cases, this means that memory management “just works” in Swift, and you do not need to think about memory management yourself. ARC automatically frees up the memory used by class instances when those instances are no longer needed.
However, in a few cases ARC requires more information about the relationships between parts of your code in order to manage memory for you. This chapter describes those situations and shows how you enable ARC to manage all of your app’s memory.
You should take a look over Automated Reference Counting.
One of the most common situation is when you have strong reference cycles between class instances, because the compiler doesn't know when to release that part of memory. Also take a look over the differences of strong and weak references.
But as even Apple saids, "In most cases", you should be ok without, but if your application crashes, it could be that you have memory issues.

Automated reference counting provides a new, simpler, way of managing reference counted objects. By automating the tasks of calling retain and release it eliminates a large class of memory leaks and invalid references caused by programmers forgetting to call memory management functions.
However, ARC does not eliminate a different class of leaks caused by logical errors in the design of your code, when your object graph has cycles. ARC provides tools for you to address this issue by adding weak references, but if you don't do it right, there is nothing ARC can do to help you.
In addition, you may have "lingering references", when an object remains in memory even though your program no longer needs it. Memory leaks of this kind can happen even in garbage-collected environments, such as Java and C#. They represent a logical error in design, and cannot be eliminated by clever compiler tricks in the current state of compiler technology.
This is when Xcode memory tools come in handy. You run them to check for memory leaks, ensuring that your code does not have cycles and "lingering references".

Related

View Controllers deinitialized still memory leak

I have deinit method in all my VCs to check if they are being deinitialized or not
deinit {
print("\(self.description) successfully deinitialized")
}
When I logout, I see all my view controllers are deinitialized and my LoginViewController becomes the root view controller. But I can still see the RAM usage as 90MB. Every time I log in and logout, it keeps increasing.
Is it possible if my view controller has deinitialized, still it can have a memory leak?
What I know is, if the view controller is deinitialized, there is no memory leak. If there is a memory leak, the view controller will not deinitialize.
Am I wrong? Please help.
UPDATE: As per Luca's suggestion, and with the help of this answer, I found out the memory leaks. But I am not able to understand any of this. Is there any way to make it more readable?
There are three types of undesired memory issues:
Abandoned memory: This is memory that you do have some lingering strong references, but for which you no longer have access to these references. The typical example is a strong reference cycle.
This is very common problem in Swift projects. You find these using the “Debug Memory Graph” feature. See iOS app with ARC, find who is owner of an object or How to debug memory leaks when Leaks instrument does not show them?.
By the way, you’ve apparently confirmed that your view controllers are being released. That’s great if that’s the case. But they’re not the only object that can be entangled in a strong reference cycle. Any reference types can get caught up in reference cycles. Use the “Debug Memory Graph” feature and review your objects in the left panel and make sure there’s nothing there that shouldn't be. (By the way, this technique saves you from having to sprinkle deinit methods all over the place.)
Cached memory: This is memory that has been allocated, and the system will hang on to it in case you might need it again, offering you high performance access. This often isn’t too worrisome unless the amount of memory consumed is huge, because when the device is placed in memory pressure, often this memory is reclaimed automatically for you.
If you use UIImage(named:) that can cache images in memory. If you use URLSession, the URLCache can cache responses.
If testing on simulator, you might want to choose “Debug” » “Simulate Memory Warning” and see how much memory is retrieved, if any.
Leaked memory: This is memory that that has been allocated, but for which you have no further references to it. Typically this is a result of some manual allocation of memory that was never deallocated.
The Leaks tool will help you find these, but this is relatively uncommon to have anything material in this category in Swift code. (Or if you do have them, they tend to be small things generated within the frameworks, not within your control.) Sure, if you’re doing manual Core Foundation (or Core Graphics) calls, you can manifest these sorts of issues, but it’s not very common.
FWIW, the leaks tool doesn’t appear to be reporting any material memory consumption. So focus on Allocations tool (or, better, the “Debug Memory Graph”, if you can). Your leaks don’t appear to be enough to account for the sort of memory loss that you’re talking about here.
Also, I’d suggest you confirm that you do not have memory diagnostics turned on. E.g. things like zombies or the like can cause growth in memory (though I wouldn’t have thought that you could approach 90mb worth). Tools like this, the malloc stack trace, etc., increase memory consumption. That’s fine while using these tools to diagnose issues, but should be turned off when you’re done.
But, bottom line, I’d focus on confirming that the problem is not abandoned or cached memory, before diving into leaks (as often the latter are small and unrelated to anything in your code). These are far more common source of issues.
Even though the ViewController is de-initialised it doesn't necessarily mean it will be deallocated. There is a possibility there is a strong reference cycle. Or maybe in your code, to avoid retain cycle you are using unowned reference somewhere, for which the reference count is not becoming zero. The object will not be de-allocated until both strong and unowned reference counts become zero. In that case try using weak instead of unowned and see if it works. Weak references point to something called side table instead of directly pointing to the object, and hence don't keep the object from getting deallocated once de-initialised
Check out this article to understand how unowned reference can sometimes keep the object from getting deallocated, and ARC in general.

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

Possible reasons for memory leaks in iOS? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm researching possible memory leak traps in iOS and I keep coming across strong reference cycles. This has become clear and the only thing mentioned that I can find regarding memory leaks, even in Apple's documentation.
What are some other causes for memory leaks to avoid?
In Objective-C, there are many types of leaks that the static analyzer (shift-command-B) can help identify. Beyond simple strong reference cycles, if you're not using ARC with Objective-C, it's extremely easy to leak. And if you're using Core Foundation objects (especially in Objective-C) and aren't careful, you can easily leak. The static analyzer is pretty good at identifying many of these simple issues.
But stepping back a little, Apple discusses three types of common memory problems:
Leaked memory: Memory that can't be accessed again.
Examples of this would be incorrect bridging of Core Foundation types, strong reference cycles, etc.
Abandoned memory: Memory that won't be accessed again.
An example of this would be a circular reference in view controllers (from A to B and to A again, rather than popping/dismissing back to A). The original A view controller still exists and could theoretically access its objects, but you won't ever do so, because you're now working with a new instance of A.
Cached memory: Memory that can be accessed again (but for which you may or may not actually access it again).
An example of this would be using imageNamed with UIImage, which caches the image in case you need it again in the future, whether you actually do or not.
Proper caching mechanisms will respond to memory pressure and purge the cache in these situations. But failure to do so can cause unbounded growth in memory.
I'd suggest watching a few WWDC videos including:
WWDC 2013 Fixing Memory Issues
WWDC 2012 iOS App Performance: Memory
There are four general cases:
If you are using Swift, memory management is done for you across the board, and the only possible way in which you can be responsible for a leak is through a retain cycle.
This can happen more easily than you might suppose. Indeed, in my own real life, the hardest cases are those where normal use of Cocoa creates a retain cycle and you don't realize it. Examples are NSNotificationCenter registration with an observer object, and WebKit's WKUserContentController (as I discuss here).
If you are using Objective-C with ARC, an additional problem is that you can mismanage CFTypeRefs. Releasing them is up to you and you can forget / fail to do this. (This problem can't arise if you're using Swift, because Swift manages CFTypeRefs for you.)
If you are using Objective-C without ARC (which would be very silly of you), you can mismanage any object, so just about anything you create can leak.
Finally, Cocoa itself sometimes leaks secondary objects in small ways, but there is usually nothing you can do about this and it's not your fault if it happens.
If you don't use ARC then memory leaks are easy to cause. If you alloc/init an object and then don't release it, or have more retains than releases, and then forget about it then the object is leaked.
ARC does not memory manage memory that is allocated using malloc/calloc. That's entirely up to you. If you malloc a block of memory, you have to free it when you'e done with it, or it gets leaked.
ARC also does not memory manage Core Foundation Objects, unless you make use of the correct bridging casts to hand control of those objects to Cocoa. So if you CFCreate a Core Foundation object and then don't CFRelease it, you've also just leaked memory.

Questions about Very Old Pre-ARC Objective-C Code

We have an app with super messy code created by some other development company long time ago. Recently we found out there was a bug inside it. After hours of debugging, we found out that if we comment out one of the release command of one of the ViewController when done using then the code works perfectly. My questions are:
Is commenting out the release command can cause significant memory leak?
Will the ARC in recent days can handle this issue (still can release the memory without release command)?
If I add code as normally writing ARC code, will the old code and new code coexist in the same file?
The code was so old so we don't want to take the risk of converting it to ARC code. If the answer to above question 3 is yes, then it will be much more comfortable for us to change it.
Randomly removing release is the same as randomly subtracting 1 from some variable because you have an off-by-one error and now it "seems to work better." Yes, it can absolutely lead to more problems. Memory management cannot be safely done by simply adding and removing retain and release until it "seems to work."
My recommendation is to let Xcode convert the code for you to ARC (Edit>Refactor>Convert to Objective-C ARC....) If you had incorrect memory management before, this is not guaranteed to fix it (particularly retain loops), but there are a wide number of mistakes that it will automatically address. Beyond that, you will need to debug the errors in memory management.
If it's not possible to convert this code to ARC, run the static analyzer (Cmd-Shift-B). You should do this anyway, even after converting to ARC. There are a lot of memory problems it can't find, but there are a lot it can.
1) it may cause a "significant" memory leak depending on what kind of object will leak, and how many times it is allocated (what if it's in a loop that iterates million times? :-)
2) ARC can be enabled / disabled on a per-file basis. You can't have ARC and NON ARC code in the same file. If you want ARC to handle that situation, you have to convert at least that file
3) as written in the answer 2, no, they can't coexist in the same file.
Last, hiding errors is always a bad practice that can give you a lot of work in the future...I suggest you to add the code that gives you the error, maybe someone can give you an hand to resolve
It's impossible to tell without seeing the code. Potentially, yes.
Yes — ARC does memory management for you.
No. ARC is done on a file level - you can't combine ARC and non-ARC code in the same file, and enabling ARC will cause all calls to retain, release and autorelease compile errors.
Yes, without releasing objects they will most likely "hang out" in memory, inaccessible to your program.
The whole reason for using ARC is to handle memory automatically. So, yes, it will release the memory without using the release message. (In fact, the compiler throws an error when you try to build a file marked for ARC with a release directive within.)
Not exactly. It is possible, but not without some compiler magic available in clang.
I'm sorry you have to see this in the hard way.
Quite possible. One single view can occupy a lot of memory in pre-ARC ages, and without properly releasing properties, a single line of code can leak a lot of memory, if called many times. I have done this before and was very excited when ARC is introduced, it's just magic. And also, if you want to see the exact result, you will like the leak tool in Instruments.
Yes! This is what ARC is made for. There is only one bad news: it requires you to convert the whole file to ARC, which you don't want to do.
No. At least not officially supported. There might be some magic, but may or may not break in some future release, and you (definitely) don't want to risk it.
I'm afraid none of the answers above can make you feel better, so you'd better get started to fix that, better in the ARC way.

What kind of leaks does automatic reference counting in Objective-C not prevent or minimize?

In the Mac and iOS platforms, memory leaks are often caused by unreleased pointers. Traditionally, it has always been of utmost importance to check your allocs, copies and retains to make sure each has a corresponding release message.
The toolchain that comes with Xcode 4.2 introduces automatic reference counting (ARC) with the latest version of the LLVM compiler, that totally does away with this problem by getting the compiler to memory-manage your stuff for you. That's pretty cool, and it does cut lots of unnecessary, mundane development time and prevent a lot of careless memory leaks that are easy to fix with proper retain/release balance. Even autorelease pools need to be managed differently when you enable ARC for your Mac and iOS apps (as you shouldn't allocate your own NSAutoreleasePools anymore).
But what other memory leaks does it not prevent that I still have to watch out for?
As a bonus, what are the differences between ARC on Mac OS X and iOS, and garbage collection on Mac OS X?
The primary memory-related problem you'll still need to be aware of is retain cycles. This occurs when one object has a strong pointer to another, but the target object has a strong pointer back to the original. Even when all other references to these objects are removed, they still will hold on to one another and will not be released. This can also happen indirectly, by a chain of objects that might have the last one in the chain referring back to an earlier object.
It is for this reason that the __unsafe_unretained and __weak ownership qualifiers exist. The former will not retain any object it points to, but leaves open the possibility of that object going away and it pointing to bad memory, whereas the latter doesn't retain the object and automatically sets itself to nil when its target is deallocated. Of the two, __weak is generally preferred on platforms that support it.
You would use these qualifiers for things like delegates, where you don't want the object to retain its delegate and potentially lead to a cycle.
Another couple of significant memory-related concerns are the handling of Core Foundation objects and memory allocated using malloc() for types like char*. ARC does not manage these types, only Objective-C objects, so you'll still need to deal with them yourself. Core Foundation types can be particularly tricky, because sometimes they need to be bridged across to matching Objective-C objects, and vice versa. This means that control needs to be transferred back and forth from ARC when bridging between CF types and Objective-C. Some keywords related to this bridging have been added, and Mike Ash has a great description of various bridging cases in his lengthy ARC writeup.
In addition to this, there are several other less frequent, but still potentially problematic cases, which the published specification goes into in detail.
Much of the new behavior, based on keeping objects around as long as there is a strong pointer to them, is very similar to garbage collection on the Mac. However, the technical underpinnings are very different. Rather than having a garbage collector process that runs at regular intervals to clean up objects no longer being pointed to, this style of memory management relies on the rigid retain / release rules we all need to obey in Objective-C.
ARC simply takes the repetitive memory management tasks we've had to do for years and offloads them to the compiler so we never have to worry about them again. This way, you don't have the halting problems or sawtooth memory profiles experienced on garbage collected platforms. I've experienced both of these in my garbage collected Mac applications, and am eager to see how they behave under ARC.
For more on garbage collection vs. ARC, see this very interesting response by Chris Lattner on the Objective-C mailing list, where he lists many advantages of ARC over Objective-C 2.0 garbage collection. I've run into several of the GC issues he describes.
ARC won't help you with non-ObjC memory, for example if you malloc() something, you still need to free() it.
ARC can be fooled by performSelector: if the compiler can't figure out what the selector is (the compiler will generate a warning on that).
ARC will also generate code following ObjC naming conventions, so if you mix ARC and MRC code you can get surprising results if the MRC code doesn't do what the compiler thinks the names promise.
I experienced memory leaks in my application due the following 4 issues:
Not invalidating NSTimers when dismissing view controllers
Forgetting to remove any observers to NSNotificationCenter when dismissing the view controller.
Keeping strong references to self in blocks.
Using strong references to delegates in view controller properties
Luckily I came across the following blog post and was able to correct them: http://www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-likely-culprits/
ARC will also not manage CoreFoundation types. You can 'bridge' them (Using CFBridgingRelease()) but only if you are going to use it as an Objective-C/Cocoa object. Note that CFBridgingRelease just decrements the CoreFoundation retain count by 1 and moves it to Objective-C's ARC.
Xcode 9 provides a great tool for finding that kind of issues. It is called: "Debug Memory Graph".
Using it you can find your leaked object by class type and you can see clearly who holds a strong reference to it, by releasing it from there solves your problem. It is also detects memory cycles.
See more info about how to use it

Resources