2

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?

TruMan1
  • 33,665
  • 59
  • 184
  • 335
  • You originally tagged this question with both Objective-C and Swift tags. There are categories of problems that plague Objective-C code, which are rare or non-existent in Swift. There are other problems that are common to both. Being a little more specific about the language and/or the types of operations you're performing, we can be more specific in our counsel. – Rob May 23 '16 at 00:11

3 Answers3

7

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:

Rob
  • 415,655
  • 72
  • 787
  • 1,044
3

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.

Community
  • 1
  • 1
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Our answers were nearly identical, but you beat me to the punch! :) You didn't mention malloc'ed memory though. – Duncan C May 22 '16 at 23:52
2

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.

Duncan C
  • 128,072
  • 22
  • 173
  • 272