What does the leaks command-line tool report for a cycle, and how would a CI job use its output?

23.9.3 · L3 · Learning

Predict first

Three calls each create an A-to-B-to-A cycle. What does leaks --atExit report?

// === main.swift ===
final class A { var b: B?; init() {} }
final class B { var a: A?; init() {} }
func make() { let a = A(); let b = B(); a.b = b; b.a = a }
make(); make(); make()
print("done")
  • 6 leaks for 192 bytes with a ROOT CYCLE
  • No leaks
  • 3 leaks for 96 bytes

Mental model. A lost-property check at closing time: it finds items nobody can claim, not the crowd that never leaves.

leaks --atExit -- ./program runs the program, pauses it just before exit and scans memory for allocations that nothing reachable references. For Swift that means retain cycles and forgotten manual allocations. In the check, three calls to a function creating an A to B and B to A cycle report 6 leaks for 192 total leaked bytes, grouped under “ROOT CYCLE” with the types and stacks, which is the same information the Memory Graph debugger shows (Q159) but scriptable. The tool exits non-zero when it finds leaks, so a CI step can fail on it.

Limits: it finds unreachable memory, so a cache that grows forever (reachable) is not a leak to it; use Allocations generations for growth (Q160). The target must be debuggable (a Release app without the get-task-allow entitlement may refuse), and objects alive at exit by design (globals) are reachable, not reported. For unit tests, assert on a weak reference becoming nil after the owner is released, and run leaks over the test host for a coarse net.

Each cycle leaks two 32-byte objects.

Common traps

  • Reading “no leaks” as “no growth”. Reachable growth is invisible to it.
  • Running it on a stripped Release build. Stacks are unreadable and it may be blocked.

They might follow up with

  • Fix? Break the cycle with weak or unowned (Q159).
  • Why 6 for 3 cycles? Each cycle holds two objects.

Related questions

  • 3.7.2 How do you find a retain cycle with the Memory Graph debugger?
  • 3.7.3 How do you use Instruments’ Allocations, Leaks and VM Tracker to track a memory problem?

← How do the malloc debugging environment variables (such as…