Debugging with LLDB
Master LLDB, the modern debugger for macOS and Linux! Learn installation, essential commands, and how to transition from GDB. Perfect for Xcode and Clang users.
Track Your Progress
Sign in to save your learning progress
What You Will Learn
- ✓Understand when to use LLDB vs GDB
- ✓Install LLDB on macOS, Linux, and Windows
- ✓Use essential LLDB commands (run, break, step, print)
- ✓Set breakpoints, conditional breakpoints, and watchpoints
- ✓Inspect variables and examine memory
- ✓Debug crashes and segmentation faults
- ✓Use LLDB GUI mode for visual debugging
- ✓Translate GDB commands to LLDB equivalents
?Why Learn LLDB?
If you're on macOS, LLDB is your primary debugger. It's also becoming the standard for modern C/C++ development across all platforms.
macOS Default
No setup needed on Mac
Faster
Modern architecture
Python Scripting
Automate debugging tasks
Note: Most LLDB commands are similar to GDB. If you know GDB, you can learn LLDB quickly!
01What is LLDB?
LLDB is a modern, high-performance debugger built as part of the LLVM project. It's the default debugger on macOS and is increasingly popular on Linux and Windows due to its modern architecture and excellent performance.
LLDB Advantages
- ✓Default on macOS — no code signing needed
- ✓Faster startup and execution than GDB
- ✓Built-in Python scripting support
- ✓Better C++, Objective-C, Swift support
- ✓Modern, extensible architecture
When to Use Which?
GDB → LLDB Command Cheat Sheet
| Action | GDB | LLDB |
|---|---|---|
| Run program | run | run |
| Set breakpoint | break main | b main |
| Next line | next | next |
| Step into | step | step |
| Print variable | print x | p x |
| Backtrace | backtrace | bt |
| Continue | continue | c |
| List breakpoints | info breakpoints | br list |
| Local variables | info locals | frame variable |
| Quit | quit | quit |
Most common commands are similar! LLDB just uses shorter aliases.
02Installing LLDB
LLDB installation varies by platform. Choose your operating system below:
macOS Installation (Easiest!)
Good news: LLDB comes pre-installed with Xcode Command Line Tools!
Install Xcode Command Line Tools (if not already installed):
xcode-select --install
Verify installation:
lldb --version
lldb-1500.0.22.8
Apple Swift version 5.9 (swiftlang-5.9.0.128.108 clang-1500.0.40.1)
Or install via Homebrew (for latest version):
brew install llvm
# LLDB is at /opt/homebrew/opt/llvm/bin/lldb
Linux Installation
Ubuntu / Debian:
sudo apt update
sudo apt install lldb
# Or for a specific version:
sudo apt install lldb-15
Fedora / Red Hat / CentOS:
sudo dnf install lldb
Arch Linux:
sudo pacman -S lldb
From LLVM official repository (latest version):
# Add LLVM repository (Ubuntu example)
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 17 # Install LLVM 17
Verify installation:
lldb --version
lldb version 15.0.7
Windows Installation
Note: LLDB on Windows is less mature than on macOS/Linux. For Windows, GDB with MinGW or Visual Studio Debugger may be better choices.
Option 1: Pre-built LLVM binaries
- Download LLVM from releases.llvm.org
- Run the installer (choose "Add LLVM to PATH")
- LLDB is included in the installation
Option 2: Using Visual Studio
- Install Visual Studio with "C++ Clang tools for Windows"
- LLDB is included with the Clang toolset
Option 3: Using MSYS2
pacman -S mingw-w64-x86_64-lldb
Option 4: WSL (Recommended for Windows)
# In WSL (Ubuntu):
sudo apt install lldb
03Compiling for LLDB
Like GDB, LLDB needs debug information. Compile with -g:
Using Clang (Recommended)
clang -g -O0 program.c -o program
Best debug experience with LLDB
Using GCC
gcc -g -O0 program.c -o program
Works, but Clang debug info is better for LLDB
# Recommended flags for debugging
clang -g -O0 -Wall -Wextra program.c -o program
# Start LLDB
lldb ./program
Why -O0?
-O0 disables optimization. With optimization enabled, variables may be optimized away, code may be reordered, and debugging becomes confusing. Use -O0 for debugging, -O2 for release.
04Starting LLDB
# Basic: Start LLDB with your program
lldb ./program
# With arguments
lldb -- ./program arg1 arg2
# Attach to running process by PID
lldb -p 12345
# Attach to running process by name
lldb -n myprogram
# Debug a core dump
lldb ./program -c core
LLDB Interface
$ lldb ./program
(lldb) target create "./program"
Current executable set to './program' (x86_64).
(lldb) _
The (lldb) prompt means LLDB is ready for commands.
05Essential LLDB Commands
LLDB uses a noun-verb command structure. Many commands have GDB-compatible aliases.
| LLDB Command | GDB Alias | Description |
|---|---|---|
| Running | ||
| process launch | run, r | Start program |
| process launch -- arg1 | run arg1 | Run with arguments |
| process continue | continue, c | Continue execution |
| process kill | kill | Stop the program |
| quit | q | Exit LLDB |
| Breakpoints | ||
| breakpoint set -n main | b main | Break at function |
| breakpoint set -l 25 | b 25 | Break at line 25 |
| breakpoint set -f file.c -l 10 | b file.c:10 | Break at file:line |
| breakpoint set -n foo -c 'x==5' | — | Conditional breakpoint |
| breakpoint list | info break | List breakpoints |
| breakpoint delete 1 | delete 1 | Delete breakpoint |
| Stepping | ||
| thread step-over | next, n | Step over function |
| thread step-in | step, s | Step into function |
| thread step-out | finish | Step out of function |
| thread step-inst | si | Step one instruction |
| Examining | ||
| frame variable | info locals | Show local variables |
| frame variable x | p x | Print variable x |
| expression x | print x, p x | Evaluate expression |
| thread backtrace | bt | Show call stack |
| source list | list, l | Show source code |
Good News: GDB Commands Work!
LLDB includes GDB-compatible aliases, so commands like run,break, next,print work just like in GDB!
06Complete Debugging Session
Let's debug a buggy program using LLDB:
1#include <stdio.h>23int calculate_average(int arr[], int size) {4 int sum = 0;5 for (int i = 0; i <= size; i++) { // BUG: should be i < size6 sum += arr[i];7 }8 return sum / size;9}1011int main() {12 int scores[] = {85, 92, 78, 95, 88};13 int avg = calculate_average(scores, 5);14 printf("Average = %d\n", avg);15 return 0;16}Step-by-Step Debugging
# Compile and start LLDB
$ clang -g -O0 buggy.c -o buggy
$ lldb ./buggy
(lldb) target create "./buggy"
# Set breakpoint at the function
(lldb) b calculate_average
Breakpoint 1: where = buggy`calculate_average + 4 at buggy.c:4
# Run the program
(lldb) run
Process 12345 launched: './buggy'
Process 12345 stopped
* thread #1, stop reason = breakpoint 1.1
frame #0: calculate_average at buggy.c:4
# Check parameters
(lldb) frame variable
(int *) arr = 0x7fff5fbff8c0
(int) size = 5
(int) sum = 0
# Print the array
(lldb) p *arr@5
(int[5]) $0 = {85, 92, 78, 95, 88}
# Set conditional breakpoint: when i reaches 5
(lldb) breakpoint set -l 6 -c 'i == 5'
Breakpoint 2: where = buggy`calculate_average + 32 at buggy.c:6
(lldb) continue
Process stopped at breakpoint 2.1
# Check the index value
(lldb) p i
(int) $1 = 5
# i = 5, but valid indices are 0-4!
# What's at arr[5]? Out of bounds!
(lldb) p arr[5]
(int) $2 = 32767
Bug Found!
Loop condition i <= size should be i < size. When i=5, we access arr[5] which is out of bounds (array has indices 0-4 only).
07Watchpoints
Watchpoints pause execution when a variable's value changes — perfect for finding where a value gets corrupted:
# Watch when a variable changes
(lldb) watchpoint set variable sum
Watchpoint created: Watchpoint 1: addr = 0x7fff5fbff8c4 size = 4
watchpoint spec = 'sum'
# Watch a memory address
(lldb) watchpoint set expression -- &x
# List watchpoints
(lldb) watchpoint list
# Delete a watchpoint
(lldb) watchpoint delete 1
08GUI Mode
LLDB has a built-in curses-based GUI that shows source, variables, and threads:
# Enable GUI mode
(lldb) gui
# Exit GUI mode: press Escape
GUI Layout
┌─ Source ────────────────────────┬─ Variables ─────────┐
│ 3 int calculate_average(...) │ arr = 0x7fff... │
│ 4 int sum = 0; │ size = 5 │
│> 5 for (int i = 0; ... │ sum = 0 │
│ 6 sum += arr[i]; │ i = 0 │
├─ Threads ───────────────────────┴─────────────────────┤
│ thread #1: stop reason = breakpoint 1.1 │
└────────────────────────────────────────────────────────┘
Use Tab to switch between panes, arrow keys to navigate.
09Debugging Crashes
$ lldb ./crash_program
(lldb) run
Process launched...
Process stopped
* thread #1, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
# See where we crashed
(lldb) bt
* frame #0: crash`main at crash.c:5
frame #1: libdyld.dylib`start + 1
# Look at the code
(lldb) frame select 0
(lldb) source list
4 int *ptr = NULL;
-> 5 *ptr = 42;
# Check the pointer
(lldb) p ptr
(int *) $0 = 0x0000000000000000
# NULL pointer — found the bug!
10GDB to LLDB Translation
If you're coming from GDB, here's a quick translation guide:
| GDB | LLDB (Canonical) | LLDB (Short) |
|---|---|---|
| run | process launch | r |
| break main | breakpoint set -n main | b main |
| break 25 | breakpoint set -l 25 | b 25 |
| next | thread step-over | n |
| step | thread step-in | s |
| finish | thread step-out | finish |
| continue | process continue | c |
| print x | expression x | p x |
| info locals | frame variable | fr v |
| backtrace | thread backtrace | bt |
| list | source list | l |
| x/10xb addr | memory read -c 10 addr | x/10xb addr |
11Quick Reference Card
Running
- run — start
- run arg1 — with args
- c — continue
- kill — stop
- q — quit
Breakpoints
- b main
- b 25
- br list
- br del 1
- watch var
Stepping
- n — step over
- s — step into
- finish — step out
- si — instruction
Examining
- p x — print
- fr v — locals
- bt — backtrace
- l — source
- gui — visual
!Code Pitfalls: Common Mistakes & What to Watch For
copied code may work on paper but crash at runtime — LLDB is your essential tool for understanding why.
On macOS, LLDB is the default debugger, and it's crucial for diagnosing issues in copied C code. When you copy code that segfaults, you can't just know "why did this crash?" — you need to run it in LLDB, set breakpoints, and trace through the execution yourself.
The Trap: Copied code can produce syntactically correct code that contains logic errors, memory bugs, or race conditions that only manifest at runtime. Without debugger skills, you're reduced to adding printf statements everywhere — a slow and ineffective approach.
The Reality: LLDB mastery makes you independent of the limitations of copied code. Use thread backtrace to find where crashes happen, frame variable to inspect state, and watchpoint to catch memory corruption. These skills let you fix common mistakes efficiently.
13Frequently Asked Questions
Q:How do I switch from GDB to LLDB?
A: LLDB supports most GDB shortcuts! Commands like b,r, n,s, p, and bt work the same. The main difference is in longer commands like breakpoint set.
Q:Why is LLDB the default on macOS?
A: LLDB is part of the LLVM project (same as Clang). Apple uses Clang as the default compiler, so LLDB integrates better with macOS and Xcode. It also supports Swift debugging natively.
Q:How do I print an array in LLDB?
A: Usep *arr@count to print count elements, or p (int[10])*arr to cast and print. For frame variable: fr v -Z 10 arr.
Q:Can I use LLDB on Linux?
A: Yes! Install withapt install lldb or similar. It works great, especially with Clang-compiled code. Many developers prefer it for its modern syntax and Python scripting.
13LLDB vs GDB: When to Use Which?
Use LLDB When:
- ✓Working on macOS
- ✓Using Xcode for iOS/macOS development
- ✓Compiling with Clang/LLVM
- ✓Debugging Swift or Objective-C
- ✓Need faster startup
Use GDB When:
- ✓Working on Linux servers
- ✓Debugging embedded systems
- ✓Using GCC toolchain
- ✓Need remote debugging
- ✓Working with legacy projects
Pro Tip
Learn both! The core concepts (breakpoints, stepping, examining) are identical. If you know GDB, you can use LLDB immediately with the GDB-compatible commands!
Test Your Knowledge
Related Tutorials
Debugging with GDB
Master the GNU Debugger! Learn to install GDB on Windows, Linux, and macOS, set breakpoints, step through code, inspect variables, and find bugs like a professional developer.
Header Files in C
Deep dive into header files! Learn to create your own .h files, understand include guards, organize declarations, and follow best practices for modular code.
Pointers in C
The most powerful feature in C! Pointers store memory addresses. Learn what they are, why they matter, and how to use them safely.
Have Feedback?
Found something missing or have ideas to improve this tutorial? Let us know on GitHub!