Xcode Visual Memory Debugger

I cannot believe it was over five years ago that I wrote about using the heapshot tool to find abandoned memory. I have never liked switching out of Xcode into Instruments for memory debugging. It is distracting and I can never remember how to use the heap and leak tools.

The good news is that Xcode 8 is bringing a new visual memory debugger. Even better is that you use it directly from the Xcode debugger so you don’t need to use Instruments.

Creating a Leak

To play with the memory graph debugger let’s create a memory leak. First we need a simple generic linked-list class:

class UYLNode<T> {
  var data: T!
  var next: UYLNode?

  init(data: T) {
    self.data = data
  }
}

Now let’s create a quick and dirty view controller that uses our generic class to build a list of Strings:

class NodeViewController: UIViewController {
  var nameList = UYLNode<String>(data: "Tom")
}

Then in the viewDidLoad method we can add to our linked list:

let names = ["Dick","Harry"]
var head = nameList
for name in names {
  let node = UYLNode<String>(data: name)
  head.next = node
  head = node
}

Now suppose we go one step further and make our list into a loop by making the tail point back to the start:

head.next = nameList

Note that the reference to the next node is a strong reference so our 3-node linked list is now in a strong retain cycle and will keep itself alive when we release the view controller.

Memory Graph Debugger

A picture is worth a thousand words so let’s use the new memory graph debugger to take a look at our objects before and after we release the view controller. You can access the tool using the new button next to the view hierarchy debugger:

Memory graph debugger button

The memory debugger breaks execution of the app and builds a visualisation of memory usage. The navigator window shows the objects created on the heap organised by type and instance. The central window shows the memory graph of the selected objects and the memory inspector shows details such as the size, class hierarchy and allocation backtrace:

Visual Memory Debugger

It can help to use the control at the bottom of the navigator to filter the type you are looking for - in this case UYLNode. The memory graph view shows our node view controller with a nameList property that references a list of three UYLNode objects.

If we now release our view controller, perhaps by popping it off the navigation stack, we can run the memory debugger again. This time we should see a runtime issue flagged in the issue navigator:

Issue Navigator Showing Leak

You can also use the debug navigator and filter by leaked blocks using the tiny ! icon:

Debug Navigator

Clicking on one of the leaked UYLNode objects will show the problem:

Memory graph

This is not a surprise - we managed to create a strong retain cycle when we made our list into a loop. Using a weak reference, manually breaking the cycle or simply not creating a loop would fix the problem - but that is not the point of this post. Give the memory graph debugger a try the next time you have a memory problem. It is a big improvement over the old heap and leak tools in Instruments.

Further Reading