This document explains the debugging and runtime diagnostics tools
available in Xcode's Diagnostics panel.
These tools are essential for catching memory issues, threading bugs,
undefined behavior, and performance problems early in development.
What it does:
Detects memory corruption issues such as: - Use-after-free - Buffer
overflows - Heap corruption - Dangling pointers
When to use:
Enable during heavy refactors or when chasing crashes like
EXC_BAD_ACCESS.
Official Docs:
https://developer.apple.com/documentation/code_diagnostics/address_sanitizer
Reference: Address Sanitizer detects runtime memory errors and increases memory usage during debugging.
What it does:
Extends Address Sanitizer to detect invalid access to stack memory after
a function has returned.
When to use:
Useful when working with unsafe pointers, C/C++, or low‑level audio
engine code.
Docs:
https://developer.apple.com/documentation/code_diagnostics/address_sanitizer
What it does:
Detects threading issues such as: - Data races - Incorrect mutex usage -
Unsafe concurrency access
When to use:
Critical for Swift concurrency, AVAudioEngine threading, and multi‑actor
architectures.
Official Docs:
https://developer.apple.com/documentation/code_diagnostics/thread_sanitizer
Reference: Thread Sanitizer identifies race conditions and threading bugs at runtime.
What it does:
Detects undefined operations like: - Integer overflow - Invalid casts -
Illegal memory operations
When to use:
Great for catching subtle logic errors that don't always crash
immediately.
Docs:
https://developer.apple.com/documentation/code_diagnostics/undefined_behavior_sanitizer
Reference: Undefined Behavior Sanitizer identifies undefined runtime operations.
What it does:
Warns when UI APIs are used off the main thread.
When to use:
Always safe to keep enabled during UI development and SwiftUI debugging.
Docs:
https://developer.apple.com/documentation/xcode/diagnosing-memory-thread-and-crash-issues-early
What it does:
Detects expensive operations running on the main thread that may cause
UI hangs.
When to use:
Helpful when optimizing performance or diagnosing sluggish UI.
Docs:
https://developer.apple.com/documentation/xcode/diagnosing-memory-thread-and-crash-issues-early
What it does:
Overwrites freed memory with patterns so invalid access is easier to
detect.
Use when:
Tracking down memory stomps or weird state corruption.
What it does:
Places guard pages around allocations to catch buffer overruns
immediately.
What it does:
Replaces malloc with a debugging allocator that isolates allocations
onto pages so invalid memory access crashes instantly.
Reference: Guard Malloc forces crashes at the exact moment memory errors occur by isolating allocations.
What it does:
Prevents deallocated Objective‑C objects from being freed so you can
detect messaging a deallocated instance.
Docs:
https://developer.apple.com/documentation/xcode/investigating-crashes-for-zombie-objects
What it does:
Records allocation stack traces so you can see where memory was created
or freed.
Useful with: - Instruments - Leaks tool - Memory Graph Debugger
- Don't ship with sanitizers enabled --- they reduce performance significantly.
- Create a dedicated Sanitizer Debug Scheme.
- Run ASan + TSan regularly in CI for stability.
- Use Guard Malloc only for deep debugging --- it is very slow.
If you're building complex apps like audio engines or concurrency-heavy systems:
✅ Address Sanitizer → Memory safety
✅ Thread Sanitizer → Actor/thread bugs
✅ Main Thread Checker → UI correctness
✅ Instruments → Performance profiling
These four together catch the majority of production crashes early.
While sanitizers help detect problems early, LLDB is often the fastest way to understand why a crash happened. When Xcode pauses execution, LLDB lets you inspect every thread, stack frame, and loaded binary in real time.
Shows the full stack trace for every thread in the process.
thread backtrace all
bt allUse this when:
- Investigating deadlocks or freezes
- Diagnosing Swift concurrency issues
- Debugging background or audio threads
Displays detailed information about the currently selected thread.
thread infoHelpful for identifying:
- QoS / priority issues
- Actor execution context
- Suspended or blocked threads
Resolves a raw memory address to the symbol and binary it belongs to.
image lookup -a 0x123456789Extremely useful when:
- Working from crash logs with raw addresses
- Debugging optimized builds
- Investigating framework or AudioUnit crashes
Inspect local variables in the current stack frame.
frame variableSwitch between threads.
thread select 5Prints an Objective-C or Swift object description.
po engine
po projectStoreShows CPU register state --- useful when debugging low-level crashes.
register read- Capture
bt allimmediately after a crash before continuing execution. - Combine LLDB with Address Sanitizer and Thread Sanitizer for maximum visibility.
- Async boundaries can hide root causes --- inspect multiple threads.
- Real-time systems often crash off the main thread, so check worker threads first.