Skip to content

01 - iOS 调试深度全栈

目录

  1. Xcode 调试概览
  2. 断点调试系统
  3. LLDB 命令详解
  4. LLDB 执行控制
  5. LLDB 内存与变量操作
  6. LLDB 高级特性
  7. LLDB 脚本与自定义命令
  8. Instruments 工具链
  9. Time Profiler 深度分析
  10. Allocations 内存分配追踪
  11. Leaks 内存泄漏检测
  12. Zombies 悬垂指针检测
  13. Core Animation 渲染分析
  14. Network & Energy 工具
  15. System Trace 系统级追踪
  16. 模拟器调试
  17. 崩溃日志分析
  18. Sanitizer 运行时检测
  19. 内存调试实战
  20. 调试与 Android/Kotlin 对比
  21. 面试考点汇总

1. Xcode 调试概览

1.1 调试工具链全景

iOS 调试工具链全景架构:

┌──────────────────────────────────────────────────────────────────────┐
│                    Xcode Debugging Ecosystem                        │
├──────────────┬──────────────────────┬───────────────────────────────┤
│              │  编译期检测           │  运行时检测                   │
│              ├──────────────────────┼───────────────────────────────┤
│  静态分析    │  ⚠️ 编译器警告       │  Sanitizers (ASan/TSan/UBSan) │
│  (Analyzer)  │  • 空值检查          │  • 地址安全检测               │
│              │  • 未使用变量        │  • 线程安全检测               │
│              │  • 内存管理          │  • 未定义行为检测             │
│              │  • 死代码检测        │                               │
│              ├──────────────────────┼───────────────────────────────┤
│  断点调试    │  LLDB 调试器         │  断点系统                     │
│  (LLDB)      │  • 变量检查          │  • 条件断点                   │
│              │  • 表达式求值        │  • 日志断点                   │
│              │  • 内存读写          │  • 异常断点                   │
│              │  • 堆栈回溯          │  • 观察断点(Watchpoint)     │
│              ├──────────────────────┼───────────────────────────────┤
│  性能分析    │  Instruments 工具集  │  模拟器/真机调试              │
│  (Profiling) │  • Time Profiler     │  • Simulator                  │
│              │  • Allocations       │  • Console (设备日志)         │
│              │  • Leaks             │  • Crash Reports              │
│              │  • Zombies           │  • GPU Frame Capture          │
│              │  • Core Animation    │  • Memory Pressure            │
│              │  • System Trace      │                               │
│              │  • Network/Energy    │                               │
└──────────────┴──────────────────────┴───────────────────────────────┘

1.2 Xcode 调试入口

Xcode 调试入口方式:

┌──────────────────────────────────────────────────────────────────────┐
│  方式              │ 快捷键         │ 说明                           │
├──────────────────────────────────────────────────────────────────────┤
│ 启动调试运行       │ ⌘ + R          │ 启动并附加 LLDB               │
│ Profile (Instruments) │ ⌘ + I   │ 打开 Instruments 分析工具     │
│ 断点导航           │ ⌘ + Shift + L │ 导航列表,搜索断点/符号        │
│ 控制台             │ ⌘ + Shift + C │ 打开/隐藏 LLDB 控制台          │
│ 调试栏             │ (显示/隐藏)    │ 显示 step/continue/stop 控制   │
│ 变量观察器         │ (自动)         │ 断点命中时自动显示变量         │
│ 内存图             │ (Instruments) │ 可视化内存布局                 │
└──────────────────────────────────────────────────────────────────────┘

关键路径:
Xcode → Product → Profile (⌘ + I)                    → Instruments
Xcode → Window → Debug Navigator (⌘ + 5)              → 调试面板
Xcode → Window → Debugging → Variables (⌘ + 6)       → 变量观察器
Xcode → Window → Debugging → Memory (⌘ + 7)          → 内存视图
Xcode → Window → Debugging → Threads (⌘ + 8)         → 线程面板
Xcode → Window → Debugging → Console (⌘ + 9)         → LLDB 控制台
Xcode → Window → Devices and Simulators (⌘ + Shift + 2) → 设备管理

1.3 断点类型详解

断点类型完整分类:

┌──────────────────────────────────────────────────────────────────────┐
│ 类型          │ 触发条件              │ 调试场景              │ 实现原理           │
├──────────────────────────────────────────────────────────────────────┤
│ 基础断点      │ 代码行号              │ 逐行调试              │ SIGTRAP 信号      │
│ 条件断点      │ 表达式为真            │ 特定数据状态          │ 条件检查+SIGTRAP  │
│ 符号断点      │ 函数/方法名           │ 拦截外部调用          │ dyld 符号解析     │
│ 异常断点      │ 抛出 Objective-C/C++ │ 捕获所有异常          │ NSException 监听   │
│                │   异常                 │                       │                   │
│ 日志断点      │ 命中时(不停止)      │ 跟踪调用流            │ NSLog + continue   │
│                │                        │                       │                   │
│ 观察断点      │ 变量读写              │ 追踪内存变更          │ 硬件断点寄存器     │
│   (Watchpoint) │                        │                       │ HW debug registers │
│ 动态断点      │ 函数进入/返回         │ 动态插入调试逻辑      │ JIT 代码注入       │
│ 崩溃断点      │ 程序崩溃              │ 定位崩溃现场          │ signal handler    │
│  Mach 异常    │                       │                       │                   │
│ 线程断点      │ 线程创建/销毁         │ 监控线程生命周期      │ pthread hooks     │
│ 库加载断点    │ 动态库加载/卸载       │ 分析库初始化          │ dyld hooks        │
│ 路径断点      │ 文件路径访问          │ 追踪文件操作          │ ktrace + VFS hook │
└──────────────────────────────────────────────────────────────────────┘

1.4 调试流程全景

iOS 完整调试流程:

开发阶段                    测试阶段                  生产阶段
    │                         │                         │
    ▼                         ▼                         ▼
┌───────────┐         ┌───────────────┐         ┌───────────────┐
│ 代码编写   │         │ Instruments   │         │ 崩溃报告      │
│ LLDB 调试  │ ──────→ │ Profiling     │ ──────→ │ Crash Reports │
│ 断点/变量  │         │ Sanitizers    │         │ dSYM 符号化   │
│ 内存检查   │         │ Simulator     │         │ TestFlight    │
└───────────┘         └───────────────┘         └───────────────┘
    │                         │                         │
    ▼                         ▼                         ▼
 修复代码              性能优化                远程分析
 验证修复              内存优化                后续版本修复

2. 断点调试系统

2.1 断点底层原理

断点(Breakpoint)底层实现原理:

┌──────────────────────────────────────────────────────────────────────┐
│ 断点设置流程(LLDB + 内核协作):                                    │
│                                                                      │
│  1. 用户设置断点 (breakpoint set --name "func")                     │
│  2. LLDB 查找符号地址 (dlopen + dladdr / dyld lookup)               │
│  3. LLDB 修改目标进程内存:                                          │
│     • x86/x86_64:将第一条指令替换为 0xCC (INT3)                   │
│     • ARM64:将第一条指令替换为 0xD4200000 (BRK #0x1)              │
│  4. 目标进程执行到断点 → CPU 触发异常                                │
│  5. 内核通过 ptrace 通知 LLDB(SIGTRAP)                             │
│  6. LLDB 接管控制权,暂停进程                                        │
│  7. 用户执行 LLDB 命令                                               │
│  8. 用户点击 continue → LLDB 恢复原始指令,进程继续执行              │
│                                                                      │
│  x86_64 断点指令替换:                                               │
│  ┌───────┬──────────┬──────────────────────────┬──────────────────┐ │
│  │ 状态   │ 机器码    │ 指令                    │ 字节数           │ │
│  ├───────┼──────────┼──────────────────────────┼──────────────────┤ │
│  │ 原始   │ 55 48 89 │ push rbp; mov rbp,rsp  │ N 字节           │ │
│  │ 断点后 │ CC       │ int 3 (SIGTRAP)          │ 1 字节 (可伸缩)  │ │
│  └───────┴──────────┴──────────────────────────┴──────────────────┘ │
│                                                                      │
│  ARM64 断点指令替换:                                                │
│  ┌───────┬──────────────┬──────────────────────────┬───────────────┐ │
│  │ 状态   │ 机器码       │ 指令                     │ 字节数        │ │
│  ├───────┼──────────────┼──────────────────────────┼───────────────┤ │
│  │ 原始   │ D10043FF     │ sub sp, sp, #0x40      │ 4 字节        │ │
│  │ 断点后 │ D4200000     │ brk #0x1               │ 4 字节        │ │
│  └───────┴──────────────┴──────────────────────────┴───────────────┘ │
└──────────────────────────────────────────────────────────────────────┘

2.2 条件断点深度分析

条件断点(Conditional Breakpoint)原理:

┌──────────────────────────────────────────────────────────────────────┐
│ 条件断点工作流程:                                                   │
│                                                                      │
│  LLDB 在条件断点处插入"检查器代码":                                 │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  原始断点: BRK #0x1                                           │   │
│  │      ↓                                                       │   │
│  │  LLDB 插入检查代码:                                           │   │
│  │  ┌──────────────────────────────────────────────────────┐   │   │
│  │  │ 1. 触发断点 (BRK #0x1)                                │   │   │
│  │  │ 2. LLDB 捕获 SIGTRAP                                  │   │   │
│  │  │ 3. 评估条件表达式 (如 i == 100)                       │   │   │
│  │  │ 4a. 条件为真 → 真正暂停,显示变量                     │   │   │
│  │  │ 4b. 条件为假 → LLDB 恢复指令,进程继续执行             │   │   │
│  │  └──────────────────────────────────────────────────────┘   │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  条件表达式支持的语言:                                              │
│  • C 表达式(默认)                                                 │
│  • Swift 表达式(Xcode 11+)                                        │
│  • OC 表达式                                                        │
│                                                                      │
│  常见条件表达式:                                                    │
│  • 数值条件:  i == 100 && j < 50                                    │
│  • 字符串条件: [name isEqualToString:@"test"]                       │
│  • 对象条件:  self.isReady == YES                                   │
│  • 线程条件:  [[NSThread currentThread] name] == @"NetworkThread"   │
│  • 崩溃条件:  exception.name == @"NSInvalidArgumentException"       │
└──────────────────────────────────────────────────────────────────────┘

2.3 日志断点(Log Point)

日志断点(Log Point / 打印断点):

┌──────────────────────────────────────────────────────────────────────┐
│ 日志断点工作流程:                                                   │
│                                                                      │
│  与条件断点的关键区别:                                              │
│  • 条件断点:命中时暂停执行                                         │
│  • 日志断点:命中时打印信息,不停止执行                               │
│                                                                      │
│  LLDB 实现方式:                                                     │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  breakpoint set --name "cellForRowAt"                        │   │
│  │        --command "expression --swift (indexPath.row, section)"│   │
│  │        --stop-hook "continue"                                │   │
│  │                                                              │   │
│  │  命中时:                                                    │   │
│  │  1. 触发断点 → LLDB 暂停                                      │   │
│  │  2. 执行 command 列表(打印日志)                              │   │
│  │  3. 自动 continue → 进程恢复                                  │   │
│  │  (整个过程对用户透明,无感知)                                 │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  日志断点应用场景:                                                  │
│  • 高频函数调用统计(cellForRowAt、scrollViewDidScroll)            │
│  • 网络请求参数记录                                                  │
│  • 动画回调追踪                                                      │
│  • 性能分析(不中断执行的情况下记录耗时)                             │
│                                                                      │
│  性能对比:                                                          │
│  ┌───────────────┬──────────────┬──────────────┬──────────────────┐ │
│  │ 方式          │ 执行开销      │ 可生产使用    │ 适用场景        │ │
│  ├───────────────┼──────────────┼──────────────┼──────────────────┤ │
│  │ NSLog         │ 高(I/O)    │ ❌ 生产禁用   │ 快速调试        │ │
│  │ 日志断点       │ 中(仅命中时)│ ✅ 条件启用   │ 生产调试        │ │
│  │ #if DEBUG     │ 零(编译期) │ ✅ 编译期剥离 │ 开发调试        │ │
│  └───────────────┴──────────────┴──────────────┴──────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘

2.4 观察断点(Watchpoint)

观察断点(Watchpoint)原理:

┌──────────────────────────────────────────────────────────────────────┐
│ 观察断点 vs 普通断点:                                               │
│                                                                      │
│  普通断点:代码地址触发 → 执行到某行时暂停                           │
│  观察断点:内存地址触发 → 访问某地址时暂停(读/写/读写)             │
│                                                                      │
│  硬件实现原理:                                                      │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │ ARM64 调试寄存器:                                             │   │
│  │                                                              │   │
│  │  DADRn (Debug Address Registers) — 存储监控地址               │   │
│  │  DACRn (Debug Access Control Registers) — 存储访问控制位      │   │
│  │    • bit[1:0]: 访问类型(1=写,2=读,3=读写)                 │   │
│  │    • bit[3:2]: 访问长度(1=1字节,2=2字节,3=4字节)          │   │
│  │    • bit[5:4]: 访问权限(0=用户态,3=特权态)                 │   │
│  │                                                              │   │
│  │  最多支持 4 个硬件观察断点(ARM64)                           │   │
│  │  超出时 LLDB 自动回退到"软件监控"(周期性读内存比较)           │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  LLDB 设置观察断点:                                                 │
│  watchpoint set variable myObject.count                              │
│  watchpoint set expression -- myView.frame.origin.x > 100          │
│  watchpoint set variable --type unsigned --size 4 *myPointer        │
│                                                                      │
│  观察断点的应用场景:                                                │
│  • 追踪变量何时被修改(bug 定位)                                   │
│  • 追踪内存泄漏(观察 dealloc 是否被调用)                          │
│  • 追踪布局属性何时被修改(AutoLayout bug)                         │
│  • 追踪动画属性何时被改变                                            │
└──────────────────────────────────────────────────────────────────────┘

2.5 异常断点

异常断点(Exception Breakpoint):

┌──────────────────────────────────────────────────────────────────────┐
│ Objective-C 异常断点:                                               │
│                                                                      │
│  工作原理:                                                          │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  NSException.raise                                             │   │
│  │      ↓                                                       │   │
│  │  objc_exception_throw()                                       │   │
│  │      ↓                                                       │   │
│  │  __cxa_throw() (底层 C++ 异常)                                │   │
│  │      ↓                                                       │   │
│  │  系统分发到 exception handler                                  │   │
│  │      ↓                                                       │   │
│  │  LLDB 监听异常事件                                             │   │
│  │      ↓                                                       │   │
│  │  命中异常断点 → 暂停进程                                      │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  配置方法:                                                          │
│  • Xcode Breakpoint Navigator → "+" → Add Exception Breakpoint      │
│  • 可选:仅捕获特定异常(NSInvalidArgumentException 等)             │
│  • 可选:仅捕获抛出时/捕获时                                        │
│                                                                      │
│  异常断点类型:                                                      │
│  ┌───────────────┬──────────────────────────────┬─────────────────┐ │
│  │ 捕获时机      │ 行为                          │ 适用场景        │ │
│  ├───────────────┼──────────────────────────────┼─────────────────┤ │
│  │ 抛出时 (C++/OC)│ 在异常抛出瞬间暂停            │ 精确捕获异常     │ │
│  │ 抛出时 (ObjC)  │ 在 objc_exception_throw     │ OC 异常定位      │ │
│  │               │  之前暂停                      │                 │ │
│  │ 捕获时        │ 在 catch 块进入时暂停         │ 异常处理调试     │ │
│  │ 所有异常      │ 所有语言/类型                  │ 全面捕获        │ │
│  └───────────────┴──────────────────────────────┴─────────────────┘ │
│                                                                      │
│  常见异常及修复:                                                    │
│  • NSRangeException — 数组越界(NSRangeException)                 │
│  • NSInvalidArgumentException — 无效参数                            │
│  • NSInternalInconsistencyException — 内部不一致                     │
│  • unrecognizedSelector — 消息发送到不响应该方法对象                │
│  • EXC_BAD_ACCESS — 野指针(非 OC 异常,是 Mach 异常)              │
└──────────────────────────────────────────────────────────────────────┘

3. LLDB 命令详解

3.1 LLDB 核心架构

LLDB(Low Level Debugger)架构:

┌──────────────────────────────────────────────────────────────────────┐
│ LLDB 架构层次:                                                      │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  Layer 1: 用户接口 (Command Line / GUI)                      │   │
│  │  ┌──────┐  ┌──────┐  ┌──────┐  ┌─────────┐  ┌───────────┐ │   │
│  │  │ CLI  │  │ GDBMI│  │ SB   │  │ Xcode   │  │ LLDB-   │ │   │
│  │  │ 命令行│  │ 协议 │  │ API  │  │ 集成    │  │ Server  │ │   │
│  │  └──────┘  └──────┘  └──────┘  └─────────┘  └───────────┘ │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                          ↓                                            │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  Layer 2: 命令解析层 (Command Interpreter)                   │   │
│  │  • 解析输入命令 → 转换为内部命令对象                          │   │
│  │  • 命令别名系统(command alias)                              │   │
│  │  • 命令补全(tab 补全)                                       │   │
│  │  • 脚本扩展(Python)                                         │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                          ↓                                            │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  Layer 3: 服务层 (Service Layer)                             │   │
│  │  • Target — 目标进程/内核                                     │   │
│  │  • Process — 运行时进程状态                                   │   │
│  │  • Thread — 线程管理                                         │   │
│  │  • Frame — 堆栈帧操作                                        │   │
│  │  • Module — 二进制模块/镜像                                   │   │
│  │  • Symbol — 符号表操作                                       │   │
│  │  • SB API (Swift Bindings)                                   │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                          ↓                                            │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  Layer 4: 平台抽象层 (Platform Abstraction)                  │   │
│  │  • iOS (ARM64, Darwin kernel)                                │   │
│  │  • macOS (x86_64/ARM64, Darwin kernel)                       │   │
│  │  • Linux (via lldb-minidebugger)                             │   │
│  │  • Windows (via lldb-windbg)                                 │   │
│  └──────────────────────────────────────────────────────────────┘   │
│                          ↓                                            │
│  ┌──────────────────────────────────────────────────────────────┐   │
│  │  Layer 5: 内核交互层 (Kernel Interface)                      │   │
│  │  • ptrace (macOS/iOS 进程控制)                               │   │
│  │  • Mach Exception Port (异常处理)                            │   │
│  │  • kdebug trace (性能追踪)                                   │   │
│  │  • dyld helper (动态链接器支持)                              │   │
│  └──────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

3.2 LLDB 命令分类速查表

LLDB 命令分类速查表:

┌───────────────┬──────────────────────────────────────────────────┐
│ 分类          │ 核心命令                                          │
├───────────────┼──────────────────────────────────────────────────┤
│ 断点管理      │ breakpoint / b / breakpoint list / bplist         │
│               │ breakpoint delete / bdel                          │
│               │ breakpoint enable / disable                       │
│               │ breakpoint set / bs / breakpoint clear / bclr     │
│               │ breakpoint command add                            │
│               │ breakpoint ignore                               │
│ 执行控制      │ continue / c / step / s / next / n / finish / f │
│               │ step-over / step-inst / step-inst-over            │
│               │ thread step-over / step-inst-over                 │
│               │ thread step-inst-over                             │
│               │ jump / thread return                              │
│ 变量/表达式   │ po / p / expr / e / fr var / fr v / frame v     │
│               │ expr -- / e --                                    │
│               │ register read / r / register write                │
│ 内存操作      │ memory read / x / memory write / xm               │
│               │ memory scan / memscan                             │
│               │ heap dump / heap query                            │
│ 线程/进程     │ thread list / thread select / thread backtrace    │
│               │ process launch / attach / run / kill              │
│               │ process status / process info                     │
│ 模块/镜像     │ image list / image lookup                         │
│               │ module list / target modules                      │
│               │ symbol lookup / image lookup --name               │
│ 汇编操作      │ disassemble / di / disas                          │
│               │ register read --raw                               │
│ 系统信息      │ platform list / platform select                   │
│               │ version / version info                            │
│ 脚本/配置     │ command alias / script / source / script import   │
│               │ settings set / settings show                      │
│ 观察点        │ watchpoint set / watchpoint list / wp             │
│               │ watchpoint delete / wp del                        │
│ 符号文件      │ sbtarget download symbol-file                     │
│               │ sbtarget clear symbol-file                        │
└───────────────┴──────────────────────────────────────────────────┘

4. LLDB 执行控制

4.1 执行控制命令详解

执行控制命令深度分析:

┌──────────────────────────────────────────────────────────────────────┐
│ 命令        │ 别名  │ 说明                          │ 与 GDB 对比           │
├─────────────┼───────┼─────────────────────────────────┼───────────────────────┤
│ continue    │ c     │ 继续执行到下一个断点            │ GDB: continue         │
│ step        │ s     │ 单步进入函数内部                │ GDB: step             │
│ next        │ n     │ 单步跳过函数(不进入)          │ GDB: next             │
│ finish      │ fi    │ 执行到当前函数返回              │ GDB: finish           │
│ step-over   │       │ 等同于 next                     │ GDB: next             │
│ step-inst   │       │ 单步指令级(汇编)              │ GDB: si               │
│ step-inst-  │       │ 单步指令级不进入                │ GDB: si               │
│ over        │       │                                 │                       │
│ jump        │       │ 跳转到指定行/地址(修改 PC)    │ GDB: jump             │
│ thread      │       │ 线程级执行控制                  │ GDB: thread           │
│ return      │       │ 直接返回当前函数(修改变量)    │ GDB: return           │
│ thread      │       │ 线程列表                        │ GDB: info thread      │
│ list        │       │                                 │                       │
│ thread      │       │ 选择线程                        │ GDB: thread select    │
│ select      │       │                                 │                       │
│ thread      │       │ 当前线程 backtrace              │ GDB: bt               │
│ backtrace   │       │                                 │                       │
│ frame       │       │ 切换堆栈帧                      │ GDB: frame            │
│ select      │       │                                 │                       │
│ frame       │       │ 切换到第 N 帧                   │ GDB: frame N          │
│ up          │       │ 上一帧(更靠近 main)            │ GDB: up               │
│ frame       │       │ 下一帧(更远离 main)            │ GDB: down             │
│ down        │       │                                 │                       │
│ frame       │       │ 获取当前帧信息                    │ GDB: frame info       │
│ info        │       │                                 │                       │
│ frame       │       │ 列出当前帧变量                    │ GDB: info locals      │
│ variables   │       │                                 │                       │
└─────────────┴───────┴─────────────────────────────────┴───────────────────────┘

执行控制流程图:

普通函数调用栈:
┌──────────────────────────────────────────────────────────────┐
│  main()                                                      │
│  ┌─ viewDidLoad() ──────────────────────────────────────┐   │
│  │  ┌─ tableView(_:cellForRowAt:) ──────────────────┐   │   │
│  │  │  ┌─ configureCell(_:) ────────────────────┐   │   │   │
│  │  │  │  ┌─ loadImage(from:) ────────────────┐ │   │   │   │
│  │  │  │  │  (异步 - 不阻塞调试)              │ │   │   │   │
│  │  │  │  └──────────────────────────────────┘ │   │   │   │
│  │  │  └─────────────────────────────────────┘   │   │   │
│  │  └─────────────────────────────────────────┘   │   │   │
│  └─────────────────────────────────────────────┘   │   │
└──────────────────────────────────────────────────────────────┘

step (s) 追踪路径:
main() → viewDidLoad() → tableView() → configureCell() → loadImage()

next (n) 追踪路径:
main() → viewDidLoad() → tableView() → configureCell() → loadImage()
                                                    (整个函数当作一步)

finish (fi) 追踪路径:
main() → viewDidLoad() → tableView() → [返回] → configureCell() → [返回]

4.2 线程控制详解

多线程调试详解:

┌──────────────────────────────────────────────────────────────────────┐
│ 多线程调试关键命令:                                                   │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 线程管理命令:                                                   │   │
│ ├────────────────────────────────────────────────────────────────┤ │
│ │ thread list                          → 列出所有线程              │   │
│ │ thread info <n>                      → 查看线程 n 详情          │   │
│ │ thread select <n>                    → 切换到线程 n             │   │
│ │ thread backtrace <n>                 → 线程 n 的调用栈          │   │
│ │ thread backtrace all                 → 所有线程的调用栈         │   │
│ │ process status                       → 进程状态                  │   │
│ │ process continue --all               → 所有线程继续             │   │
│ │ process continue --stop-others       → 仅当前线程继续           │   │
│ │ thread step-over --threads all       → 所有线程单步过           │   │
│ │ thread step-inst-over --threads all  → 所有线程指令单步过       │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 多线程调试策略:                                                     │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 策略          │ 方法                              │ 适用场景  │   │
│ ├────────────────────────────────────────────────────────────────┤ │
│ │ 全部停止      │ process continue --stop-others    │ 全局调试 │   │
│ │ 线程暂停      │ thread schedule                   │ 观察调度 │   │
│ │ 跨线程追踪    │ thread backtrace all              │ 关系分析 │   │
│ │ 线程暂停      │ thread stop                       │ 独立调试 │   │
│ │ 死锁检测      │ thread backtrace all + lock 分析  │ 死锁定位 │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 常见多线程调试场景:                                                 │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 场景          │ 调试方法                                      │   │
│ ├────────────────────────────────────────────────────────────────┤ │
│ │ 数据竞争      │ TSan + thread backtrace all                  │   │
│ │ 死锁          │ thread list + thread info (查看 lock 状态)    │   │
│ │ 线程泄漏      │ thread list + 对比快照                        │   │
│ │ 线程调度      │ thread step-over --threads all               │   │
│ │ GCD 队列      │ breakpoint set --name "dispatch_async"       │   │
│ │ 主线程阻塞    │ 检查主线程 backtrace(tid=0x1)              │   │
│ │ 后台线程崩溃  │ thread backtrace all + 检查非主线程           │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

5. LLDB 内存与变量操作

5.1 变量查看与表达式求值

变量查看和表达式求值完整指南:

┌──────────────────────────────────────────────────────────────────────┐
│ 变量查看命令对比:                                                   │
│                                                                      │
│ ┌─────────┬──────────────────────────┬───────────────────────────┐  │
│ │ 命令    │ 功能                     │ 输出示例                  │  │
│ ├─────────┼──────────────────────────┼───────────────────────────┤  │
│ │ po      │ Objective-C 对象(调 description) │ <UIView: 0x600003fa0>  │  │
│ │         │ → 调用 -description 或       │ <MyModel: 0x600003f20> │  │
│ │         │  Swift's description         │ 属性: 值               │  │
│ │ p       │ C/基本类型值               │ (int) $0 = 42           │  │
│ │         │ → 直接值输出               │ (float) $1 = 3.14       │  │
│ │ e       │ 执行表达式(求值+修改)    │ (void)                  │  │
│ │         │ → 可修改变量               │ (void) $2 = 0.5         │  │
│ │ fr var  │ 当前帧所有变量             │ (int) _count = 42       │  │
│ │         │ → 局部变量 + 参数         │ (NSString *) _name = ... │  │
│ │ frame v │ 同上(短别名)           │                           │  │
│ │ v       │ 实例变量(ivar)          │ (id) $3 = @"hello"       │  │
│ │ ivar    │                           │                           │  │
│ │ register│ 寄存器状态                 │ (uint64_t) $x0 = 0x...  │  │
│ │ read    │                           │ (uint64_t) $x1 = 0x...  │  │
│ └─────────┴──────────────────────────┴───────────────────────────┘  │
│                                                                      │
│ 表达式求值的高级用法:                                               │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ Swift 表达式求值:                                             │   │
│ │ • e self.view.alpha = 0.5         → 运行时修改 UI             │   │
│ │ • e self.data.append("new")       → 运行时添加数据            │   │
│ │ • e print("debug: \(self.name)")  → 运行时打印                │   │
│ │ • e self.tableView.reloadData()   → 运行时刷新                │   │
│ │ • e self.navigationController?.popViewController(animated: true)│   │
│ │                                                                │   │
│ │ Objective-C 表达式求值:                                       │   │
│ │ • e (void)[self.tableView reloadData]                         │   │
│ │ • e (NSString *)[self valueForKey:@"name"]                    │   │
│ │ • e (CGRect)[self.view convertRect:self.view.frame            │   │
│ │                        toView:nil]                             │   │
│ │                                                                │   │
│ │ 跨语言求值注意事项:                                           │   │
│ │ • Swift 表达式用 --swift 前缀:e --swift self.count           │   │
│ │ • OC 表达式用 (void) 等类型前缀                               │   │
│ │ • 表达式可以修改运行时状态(危险但强大)                        │   │
│ │ • 表达式在调试器上下文中执行,不是原进程的上下文               │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

5.2 内存查看与修改

内存查看与修改详解:

┌──────────────────────────────────────────────────────────────────────┐
│ 内存查看命令:                                                       │
│                                                                      │
│ ┌─────────┬──────────────────────────┬───────────────────────────┐  │
│ │ 命令    │ 功能                     │ 示例                      │  │
│ ├─────────┼──────────────────────────┼───────────────────────────┤  │
│ │ memory  │ 读取指定地址内存           │ x 0x600003fa0000 16        │  │
│ │ read    │ (hex 格式输出)         │ x/16xb 0x...             │  │
│ │         │                          │ x/16xw 0x...             │  │
│ │         │                          │ x/16xd 0x...             │  │
│ │         │                          │ x/16hx 0x...             │  │
│ │ memory  │ 写入内存                   │ xm 0x600003fa0000 42      │  │
│ │ write   │                           │ xmw 0x600003fa0000 0xff   │  │
│ │ memscan │ 内存扫描                 │ memscan 0x600000000000    │  │
│ │         │                           │    1024 "test"            │  │
│ │ heap    │ 堆转储                   │ heap dump                  │
│ │ dump    │                           │                            │
│ │ heap    │ 堆查询                   │ heap query NSObject        │
│ │ query   │                           │                            │
│ │ class   │ 类信息                   │ class dump MyClass         │
│ │ dump    │                           │                            │
│ │ property│ 属性列表                 │ property list MyClass      │
│ │ list    │                           │                            │
│ │ method  │ 方法列表                   │ method list MyClass        │
│ │ list    │                           │                            │
│ └─────────┴──────────────────────────┴───────────────────────────┘  │
│                                                                      │
│ memory read 输出格式说明:                                           │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 格式符    │ 含义              │ 示例输出                          │ │
│ ├────────────────────────────────────────────────────────────────┤ │
│ │ x         │ 十六进制          │ 0x7fff5fbff8e4                 │ │
│ │ d         │ 十进制有符号      │ 140735162879876               │ │
│ │ u         │ 十进制无符号      │ 140735162879876               │ │
│ │ f         │ 浮点数            │ 3.141592653                   │ │
│ │ a         │ 地址              │ 0x7fff5fbff8e4                │ │
│ │ c         │ 字符              │ 'A'                            │ │
│ │ s         │ 字符串            │ "Hello"                        │ │
│ │ i         │ 汇编指令          │ push %rbp                      │ │
│ │ b         │ 单字节 (byte)     │ 0x41                           │ │
│ │ h         │ 双字节 (half)     │ 0x1234                         │ │
│ │ w         │ 四字节 (word)     │ 0x12345678                     │ │
│ │ g         │ 八字节 (giant)    │ 0x123456789abcdef0             │ │
│ │ n         │ 每 n 字节换行     │ x/16xb (每字节一行)            │ │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 内存扫描实用示例:                                                   │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 搜索特定字符串:                                               │   │
│ │ memscan 0x600000000000 1024 "test"                            │   │
│ │                                                                │   │
│ │ 搜索对象地址:                                                 │   │
│ │ memscan 0x600000000000 1024 myObjectAddress                    │   │
│ │                                                                │   │
│ │ 搜索特定模式(整数):                                          │   │
│ │ memscan 0x600000000000 1024 0x12345678                       │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

5.3 类、属性、方法信息查看

类/属性/方法信息查询:

┌──────────────────────────────────────────────────────────────────────┐
│ 类信息查询(class dump):                                           │
│                                                                      │
│ LLDB 类信息查询命令:                                                │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 命令                                        │ 功能              │   │
│ ├────────────────────────────────────────────────────────────────┤ │
│ │ class dump MyClass                         │ 打印类所有信息     │   │
│ │ property list MyClass                      │ 打印属性列表       │   │
│ │ method list MyClass                        │ 打印方法列表       │   │
│ │ class dump -c MyClass                      │ 类信息摘要         │   │
│ │ property list MyClass -i                   │ 实例属性           │   │
│ │ property list MyClass -c                   │ 类属性             │   │
│ │ method list MyClass -i                     │ 实例方法           │   │
│ │ method list MyClass -c                     │ 类方法             │   │
│ │ property list MyClass -p                   │ 带属性修饰符       │   │
│ │ method list MyClass -t                     │ 带类型签名         │   │
│ │ property list MyClass -v                   │ 带变量信息         │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 输出示例:                                                           │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ class dump MyClass                                              │   │
│ │ ┌─────────────────────────────────────────────────────────┐    │   │
│ │ │ @interface MyClass : NSObject                            │    │   │
│ │ │ @property (nonatomic, strong) NSString *name;            │    │   │
│ │ │ @property (nonatomic, assign) NSInteger count;           │    │   │
│ │ │ - (void)doSomething;                                     │    │   │
│ │ │ + (instancetype)sharedInstance;                          │    │   │
│ │ │ @end                                                     │    │   │
│ │ └─────────────────────────────────────────────────────────┘    │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ image lookup 地址解析:                                              │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ image lookup --address 0x12345678                              │   │
│ │ // 输出:                                                      │   │
│ │   Address: MyApp[0x1234] (MyApp.framework.MyClass.method)      │   │
│ │   Summary: MyClass::method()                                   │   │
│ │   Module: file = "MyApp.framework"                             │   │
│ │     base addr = 0x100000000                                    │   │
│ │     CompileUnit: id = 0x0, file = "MyClass.swift",             │   │
│ │       language = "Swift"                                       │   │
│ │     Function: id = 0x0, name = "MyClass.method()",             │   │
│ │       file = "MyClass.swift",                                  │   │
│ │       begin = 0x1234, end = 0x1250                            │   │
│ │     Lines: #10 @"method()"                                     │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

6. LLDB 高级特性

6.1 动态断点(Dynamic Breakpoint)

动态断点(Dynamic Breakpoint):

┌──────────────────────────────────────────────────────────────────────┐
│ 动态断点 vs 静态断点:                                               │
│                                                                      │
│ ┌─────────────────┬──────────────────────┬───────────────────────┐  │
│ │ 特性            │ 动态断点              │ 静态断点              │  │
│ ├─────────────────┼──────────────────────┼───────────────────────┤  │
│ │ 设置时机        │ 运行时动态插入          │ 运行前设置            │  │
│ │ 代码修改        │ 需要动态代码注入        │ 断点处修改            │  │
│ │ 适用场景        │ 拦截无法提前设置断点    │ 已知代码位置          │  │
│ │                 │   的代码                │                       │  │
│ │ 性能开销        │ 高(动态编译)          │ 低(仅 SIGTRAP)      │  │
│ │ 跨语言支持      │ C/C++/OC                │ 所有语言              │  │
│ │ Swift 支持      │ ❌                      │ ✅                    │  │
│ │ 需要 root       │ ❌(LLDB 自动处理)    │ ❌                    │  │
│ └─────────────────┴──────────────────────┴───────────────────────┘  │
│                                                                      │
│ 动态断点设置:                                                       │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 拦截特定函数进入:                                              │   │
│ │ breakpoint set --name "pushViewController:animated:"           │   │
│ │ 拦截函数返回:                                                   │   │
│ │ breakpoint set --name "pushViewController:animated:"           │   │
│ │        --kind "function-return"                                │   │
│ │ 拦截方法进入+返回:                                              │   │
│ │ breakpoint set --name "tableView:cellForRowAtIndexPath"        │   │
│ │        --one-shote                                             │   │
│ │ 拦截类的所有方法:                                              │   │
│ │ breakpoint set --class MyClass                                 │   │
│ │ 拦截模块中所有符号:                                            │   │
│ │ breakpoint set --module "MyApp"                                │   │
│ │ 拦截 dyld 动态加载的符号:                                     │   │
│ │ breakpoint set --func-regex "loadLibrary.*"                    │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

6.2 符号断点与库加载断点

符号断点与库加载断点:

┌──────────────────────────────────────────────────────────────────────┐
│ 符号断点(Symbol Breakpoint):                                      │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 设置方式:                                                     │   │
│ │ breakpoint set --name "UIApplicationMain"                     │   │
│ │ breakpoint set --name "*-[UIViewController viewDidLoad]"      │   │
│ │ breakpoint set --func-regex ".*ViewController.*"              │   │
│ │ breakpoint set --module "UIKit" --name "pushViewController"    │   │
│ │                                                                │   │
│ │ 应用场景:                                                     │   │
│ │ • 拦截系统框架方法(如 UIKit 内部调用)                        │   │
│ │ • 拦截第三方库方法                                            │   │
│ │ • 拦截所有 ViewController 生命周期方法                        │   │
│ │ • 拦截所有网络请求方法                                        │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 库加载断点(Library Load Breakpoint):                              │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 设置方式:                                                     │   │
│ │ breakpoint set --library "libswiftCore.dylib"                 │   │
│ │ breakpoint set --library "libsystem*"                         │   │
│ │ breakpoint set --library "MyCustomFramework"                   │   │
│ │ breakpoint set --library-load "MyCustomFramework"              │   │
│ │                                                                │   │
│ │ 应用场景:                                                     │   │
│ │ • 追踪库加载时机和顺序                                          │   │
│ │ • 分析库初始化时间                                              │   │
│ │ • 查找重复加载的库                                              │   │
│ │ • 分析库冲突问题                                                │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 库加载断点工作流程:                                                 │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │  进程启动                                                      │   │
│ │      ↓                                                         │   │
│ │  dyld 加载主二进制文件                                          │   │
│ │      ↓                                                         │   │
│ │  dyld 加载依赖库(按依赖顺序)                                    │   │
│ │      ↓                                                         │   │
│ │  命中库加载断点 → LLDB 暂停                                     │   │
│ │      ↓                                                         │   │
│ │  可检查加载的库:                                                │   │
│ │  image list → 列出所有加载的镜像                                 │   │
│ │  image lookup --address <addr> → 查找地址所在的镜像              │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

6.3 断点条件与操作

断点条件与操作(Breakpoint Conditions & Actions):

┌──────────────────────────────────────────────────────────────────────┐
│ 断点操作类型:                                                       │
│                                                                      │
│ ┌─────────────────┬──────────────────────────────────────────────┐  │
│ │ 类型            │ 说明                                        │  │
│ ├─────────────────┼──────────────────────────────────────────────┤  │
│ │ 暂停(默认)    │ 命中时暂停进程,显示上下文                    │  │
│ │ 打印日志        │ 命中时执行命令(如 po/p),不停止             │  │
│ │ 忽略 N 次       │ 前 N 次命中忽略,第 N+1 次暂停               │  │
│ │ 执行脚本        │ 命中时执行 Python 脚本                        │  │
│ │ 记录日志到文件  │ 命中时写入指定文件                            │  │
│ │ 条件暂停        │ 满足条件时才暂停                              │  │
│ │ 连续断点        │ 一次设置多个位置                              │  │
│ └─────────────────┴──────────────────────────────────────────────┘  │
│                                                                      │
│ 复杂断点配置示例:                                                   │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 1. 条件 + 日志断点:                                           │   │
│ │    breakpoint set --name "cellForRowAt"                        │   │
│ │          --condition "indexPath.row > 10"                      │   │
│ │          --command "log"                                        │   │
│ │                                                                │   │
│ │ 2. 忽略 N 次后暂停:                                           │   │
│ │    breakpoint set --name "scrollViewDidScroll"                 │   │
│ │          --ignore 99                                            │   │   │
│ │    // 前 99 次忽略,第 100 次暂停                             │   │
│ │                                                                │   │
│ │ 3. 断点命令列表:                                               │   │
│ │    breakpoint command add 1                                    │   │
│ │    > expression --swift print("Debug: \\(self.count)")        │   │
│ │    > po self.tableView                                        │   │
│ │    > expr self.tableView.reloadData()                         │   │
│ │    > continue                                                   │   │
│ │    > end                                                        │   │
│ │                                                                │   │
│ │ 4. 线程特定断点:                                              │   │
│ │    breakpoint set --name "doSomething"                         │   │
│ │          --thread 3                                            │   │
│ │                                                                │   │
│ │ 5. 模块特定断点:                                              │   │
│ │    breakpoint set --module "Alamofire" --name "request"        │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

7. LLDB 脚本与自定义命令

7.1 LLDB 配置文件

LLDB 配置文件与自定义:

┌──────────────────────────────────────────────────────────────────────┐
│ 配置文件位置:                                                       │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 用户配置:  ~/.lldbinit                                          │   │
│ │ 项目配置:  .lldbinit (项目根目录)                               │   │
│ │ Xcode 配置:~/Library/Developer/Xcode/UserData/LLDB/            │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 常用 .lldbinit 配置:                                                │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │  # 彩色 LLDB 输出                                               │   │
│ │  command alias colors script import lldb_colors                │   │
│ │  colors on                                                      │   │
│ │                                                                │   │
│ │  # 自定义别名                                                    │   │
│ │  command alias ps "frame variable"                               │   │
│ │  command alias pb "breakpoint list"                              │   │
│ │  command alias pc "process status"                               │   │
│ │  command alias pt "thread backtrace all"                         │   │
│ │  command alias ppo "po"                                          │   │
│ │                                                                │   │
│ │  # 自动 rebase(跨平台调试)                                    │   │
│ │  command script install lldb_rebase.py                          │   │
│ │                                                                │   │
│ │  # Swift 调试增强                                              │   │
│ │  settings set target.skip-simlib true                           │   │
│ │  settings set target.load-cstr-common-strings true              │   │
│ │                                                                │   │
│ │  # 断点颜色配置                                                │   │
│ │  breakpoint color set 1 red                                    │   │
│ │  breakpoint color set 2 green                                  │   │
│ │  breakpoint color set 3 blue                                   │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

7.2 LLDB Python 脚本扩展

LLDB Python 脚本扩展:

┌──────────────────────────────────────────────────────────────────────┐
│ LLDB 脚本扩展机制:                                                  │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 脚本注册方式:                                                 │   │
│ │                                                              │   │
│ │ 方式 1: Python 文件 (.py)                                      │   │
│ │   command script import /path/to/script.py                   │   │
│ │                                                              │   │
│ │ 方式 2: .lldbinit 中 inline                                   │   │
│ │   command script add -f my_module.my_function my_command     │   │
│ │                                                              │   │
│ │ 方式 3: Xcode 插件                                            │   │
│ │   ~/Library/Developer/Xcode/UserData/LLDB/Support/           │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 实用 Python 脚本示例:                                               │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ #!/usr/bin/env python3                                         │   │
│ │ # lldb_expression.py                                            │   │
│ │                                                                │   │
│ │ import lldb                                                    │   │
│ │                                                                │   │
│ │ def swift_print(debugger, command, result, _):                │   │
│ │     '''Swift print 命令'''                                      │   │
│ │     target = debugger.GetSelectedTarget()                      │   │
│ │     process = target.GetProcess()                              │   │
│ │     thread = process.GetSelectedThread()                      │   │
│ │     frame = thread.GetSelectedFrame()                          │   │
│ │     expr_result = frame.EvaluateExpression(                    │   │
│ │         f"print({command})",                                    │   │
│ │         options=lldb.SBExpressionOptions()                      │   │
│ │     )                                                           │   │
│ │     result.AppendMessage(expr_result.GetError())               │   │
│ │                                                                │   │
│ │ def dump_all_ivars(debugger, command, result, _):             │   │
│ │     '''Dump all ivars of current object'''                     │   │
│ │     target = debugger.GetSelectedTarget()                      │   │
│ │     process = target.GetProcess()                              │   │
│ │     thread = process.GetSelectedThread()                      │   │
│ │     frame = thread.GetSelectedFrame()                          │   │
│ │     obj = frame.EvaluateExpression("self").GetObject();        │   │
│ │     if obj.IsValid():                                           │   │
│ │         cls_name = obj.GetType().GetName()                     │   │
│ │         for i in range(100):  # 假设最多 100 个 ivar           │   │
│ │             ivar = frame.EvaluateExpression(                    │   │
│ │                 f"*(id *)(((char *){obj}) + {i*8})")           │   │
│ │             if ivar.IsValid() and ivar.GetValueAsLong() != 0:  │   │
│ │                 result.AppendMessage(f"  ivar[{i}]: {ivar}")   │   │
│ │                                                                │   │
│ │ def __lldb_init_module(debugger, _):                           │   │
│ │     debugger.HandleCommand(                                    │   │
│ │         "command script add -f swift_print swprint")           │   │
│ │     debugger.HandleCommand(                                    │   │
│ │         "command script add -f dump_all_ivars dump_ivars")    │   │
│ │     print("LLDB scripts loaded!")                              │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 常用 LLDB Python 脚本库:                                            │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ • lldbexpr — Python 表达式解析工具                             │   │
│ │ • lldbplatform — 平台相关操作                                   │   │
│ │ • lldbutil — 通用调试工具                                       │   │
│ │ • SB API — Target/Process/Thread/Frame/Symbol 的 Python 绑定   │   │
│ │ • SwiftSupport — Swift 类型信息                                │   │
│ │ • ObjCSupport — Objective-C 运行时支持                         │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

7.3 LLDB 实用技巧

LLDB 实用技巧汇总:

┌──────────────────────────────────────────────────────────────────────┐
│ 实用技巧 1:修改变量(运行时热修复)                                │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ // 在断点处修改 UI 属性(无需重新编译):                       │   │
│ │ e -- swift self.view.backgroundColor = .red                   │   │
│ │ e -- swift self.label.text = "Modified!"                      │   │
│ │ e -- swift self.tableView.reloadData()                        │   │
│ │                                                                │   │
│ │ // 修改数据(无需重新生成):                                   │   │
│ │ e -- swift self.data.append("Hot Fix")                         │   │
│ │ e -- swift self.users[0].name = "Patched Name"                │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 实用技巧 2:检查调用栈(快速定位问题)                              │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ // 查看当前调用栈                                                 │   │
│ │ bt → backtrace                                                   │   │
│ │ thread backtrace → 当前线程调用栈                                 │   │
│ │ thread backtrace all → 所有线程调用栈                             │   │
│ │ frame info → 当前帧信息                                           │   │
│ │ frame variable → 当前帧变量                                       │   │
│ │ register read → 寄存器值                                          │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 实用技巧 3:内存调试                                                 │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ // 查看对象内存布局                                                │   │
│ │ ivar save propertyName → 获取 ivar 地址                           │   │
│ │ memory read <addr> → 读取内存内容                                 │   │
│ │ heap dump → 堆快照                                               │   │
│ │ heap query ClassName → 查询对象实例                               │   │
│ │ memscan <addr> <size> <value> → 搜索内存                         │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 实用技巧 4:调试技巧                                                   │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ // 动态插入断点                                                    │   │
│ │ breakpoint set --name "newFunction"                              │   │
│ │                                                                │   │
│ │ // 临时修改变量值                                                 │   │
│ │ e -- swift myVar = newValue                                     │   │
│ │                                                                │   │
│ │ // 执行方法但不修改状态                                            │   │
│ │ e -- swift _ = myMethod()                                       │   │
│ │                                                                │   │
│ │ // 查看运行时类信息                                                 │   │
│ │ po [obj class]                                                  │   │
│ │ po [obj class] superclass                                       │   │
│ │ property list MyClass                                           │   │
│ │ method list MyClass                                             │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

8. Instruments 工具链

8.1 Instruments 工具全景

Instruments 工具链全景:

┌──────────────────────────────────────────────────────────────────────┐
│                                                                    │
│  Instruments 工具分类:                                              │
│                                                                    │
│  ┌──────────────────┬────────────────────────────────────────────┐ │
│  │ 性能分析类       │ 内存分析类       │ 系统级工具      │ 安全工具 │ │
│  ├──────────────────┼────────────────────────────────────────────┤ │
│  │ • Time Profiler │ • Allocations  │ • System Trace  │ ASan    │ │
│  │ • Allocations    │ • Leaks         │ • Energy Log   │ TSan    │ │
│  │ • Core Animation │ • Zombies       │ • File Activity│ UBSan   │ │
│  │ • GPU Profiler   │ • Activity Mon. │ • Network      │ Leak-   │ │
│  │ • Metal Shader   │ • VM Tracker    │ • Time Prof.  │ Canary  │ │
│  │ • Thread Activ. │ • ObjectAlloc   │ • Disk Utility │         │ │
│  └──────────────────┴────────────────────────────────────────────┘ │
│                                                                    │
│  各工具详细对比:                                                   │
│  ┌────────────────┬───────────┬───────────┬───────────┬─────────┐ │
│  │ 工具           │ 检测内容  │ 开销     │ 实时性   │ 输出    │ │
│  ├────────────────┼───────────┼───────────┼───────────┼─────────┤ │
│  │ Time Profiler │ CPU 时间   │ 低       │ 实时    │ 火焰图  │ │
│  │ Allocations   │ 内存分配   │ 中       │ 实时    │ 图表+表 │ │
│  │ Leaks         │ 内存泄漏   │ 低       │ 实时    │ 列表    │ │
│  │ Zombies       │ 野指针     │ 高       │ 实时    │ 异常    │ │
│  │ Core Anim.    │ 渲染性能   │ 中       │ 实时    │ 帧图    │ │
│  │ Network       │ 网络流量   │ 低       │ 实时    │ 请求列表│ │
│  │ Energy Log    │ 能耗       │ 低       │ 实时    │ 图表    │ │
│  │ System Trace  │ 系统调用   │ 中       │ 离线    │ 追踪图  │ │
│  │ Metal Shader  │ GPU 着色   │ 中       │ 实时    │ 着色列表│ │
│  │ File Activity │ 文件 I/O   │ 低       │ 实时    │ 文件列表│ │
│  │ GPU Profiler  │ GPU 管线   │ 中       │ 实时    │ 帧分析  │ │
│  │ Thread Activ. │ 线程生命   │ 低       │ 实时    │ 线程图  │ │
│  │ Activity Mon. │ 进程活动   │ 低       │ 实时    │ 列表    │ │
│  │ VM Tracker    │ 虚拟内存   │ 低       │ 实时    │ 图表    │ │
│  │ ObjectAlloc   │ Obj-C 对象 │ 低       │ 实时    │ 对象图  │ │
│  └────────────────┴───────────┴───────────┴───────────┴─────────┘ │
└──────────────────────────────────────────────────────────────────────┘

8.2 Instruments 使用流程

Instruments 标准使用流程:

┌──────────────────────────────────────────────────────────────────────┐
│ 完整工作流程:                                                       │
│                                                                      │
│  1. 启动 Instruments                                                │
│     Xcode → Product → Profile (⌘ + I)                              │
│     或 open-instruments MyApp.app                                    │
│                                                                      │
│  2. 选择目标设备                                                    │
│     • Device(真机)→ USB 连接,更精确                               │
│     • Simulator(模拟器)→ 快速测试,性能有差异                       │
│                                                                      │
│  3. 选择分析工具                                                    │
│     • 性能分析 → Time Profiler                                       │
│     • 内存分析 → Allocations / Leaks                                 │
│     • 渲染分析 → Core Animation                                      │
│     • 网络分析 → Network                                             │
│     • 能耗分析 → Energy Log                                          │
│     • 系统追踪 → System Trace                                        │
│                                                                      │
│  4. 执行测试场景                                                    │
│     • 模拟用户操作流程                                               │
│     • 覆盖关键路径                                                   │
│     • 包含异常情况                                                   │
│                                                                      │
│  5. 分析结果                                                        │
│     • 查看图表变化                                                   │
│     • 定位热点函数                                                   │
│     • 检查内存增长                                                   │
│     • 分析调用栈                                                     │
│                                                                      │
│  6. 优化并验证                                                      │
│     • 修改代码                                                       │
│     • 重新 Profile → 对比结果                                       │
│                                                                      │
│  快捷键:                                                            │
│  ┌──────────────┬─────────────────────────────────────────────────┐ │
│  │ ⌘ + R        │ 开始/停止录制                                    │ │
│  │ ⌘ + S        │ 创建快照(Snapshot)                              │ │
│  │ ⌘ + E        │ 退出 Instruments                                 │ │
│  │ ⌘ + 数字     │ 快速切换工具                                     │ │
│  │ 0-9          │ 切换左侧工具列表                                 │ │
│  │ ⌘ + Option + │ 显示/隐藏时间标尺                                │ │
│  │ + 0           │                                                 │ │
│  └──────────────┴─────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘

8.3 Instruments 工具深度对比

Instruments 工具深度对比表:

┌──────────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
│ 维度             │ Time Prof   │ Allocations  │ Leaks        │ Zombies      │
│                  │ iler         │              │              │              │
├──────────────────┼──────────────┼──────────────┼──────────────┼──────────────┤
│ 核心用途         │ CPU 性能分析 │ 内存分配追踪 │ 内存泄漏检测 │ 野指针检测   │
│ 检测机制         │ 采样(1kHz)   │ 内存hook     │ 标记-清除    │ 对象替换     │
│ 检测内容         │ 函数耗时     │ 分配/释放    │ 不可达内存   │ 释放后访问   │
│ 实时性           │ 实时         │ 实时         │ 实时         │ 实时         │
│ 性能开销         │ 低(采样)     │ 中           │ 低           │ 高(替换)     │
│ 主要指标         │ 样本数/耗时  │ Live Bytes   │ 泄漏字节数   │ 僵尸对象数   │
│                  │              │ Allocs       │ Allocs/Refs  │ 异常位置     │
│                  │              │ Bytes        │              │              │
│                  │              │ Retained     │              │              │
│                  │              │ Size         │              │              │
│ 适用场景         │ 卡顿分析     │ 内存增长     │ 内存泄漏     │ 野指针崩溃   │
│                  │ 热点函数     │ 内存峰值     │ 循环引用     │ 崩溃定位     │
│                  │ 调用链分析   │ 分配频率     │ 资源未释放   │ 访问越界     │
│ 输出可视化       │ 火焰图       │ 内存柱状图   │ 泄漏列表     │ 崩溃位置     │
│                  │ + 调用树     │ + 分配树     │ + 调用栈     │ + 异常信息   │
│ 与其他工具关系   │ 配合         │ 配合 Leaks   │ 配合         │ 配合         │
│                  │ Allocations  │ 使用         │ Allocations  │ Allocations  │
│ 常见误报         │ 系统调用     │ 真实泄漏     │ 暂存内存     │ 正常         │
│                  │ (可过滤)     │ (需分析)     │ (需排除)     │   使用       │
└──────────────────┴──────────────┴──────────────┴──────────────┴──────────────┘

9. Time Profiler 深度分析

9.1 Time Profiler 原理

Time Profiler 采样原理深度分析:

┌──────────────────────────────────────────────────────────────────────┐
│ Time Profiler 采样机制:                                             │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 采样原理:                                                      │   │
│ │                                                              │   │
│ │  1. LLDB/Instruments 使用 ptrace + mach 异常端口               │   │
│ │  2. 每隔固定间隔(默认 1ms = 1000Hz)发送 SIGPROF 信号        │   │
│ │  3. 内核暂停进程,保存当前寄存器状态                            │   │
│ │  4. 通过 symbolication 将地址映射到函数名                      │   │
│ │  5. 将调用栈入栈到采样树                                        │   │
│ │  6. 恢复进程继续执行                                            │   │
│ │                                                              │   │
│ │  采样频率与精度:                                               │   │
│ │  ┌───────────┬────────────────┬───────────────┬────────────┐ │   │
│ │  │ 采样率     │ 精度           │ 开销          │ 适用场景  │ │   │
│ │  ├───────────┼────────────────┼───────────────┼────────────┤ │   │
│ │  │ 100Hz     │ 粗粒度         │ 极低          │ 概览     │ │   │
│ │  │ 1000Hz    │ 标准(默认)     │ 低            │ 一般分析  │ │   │
│ │  │ 4000Hz    │ 精细           │ 中            │ 精细分析  │ │   │
│ │  │ 10000Hz   │ 极高           │ 高            │ 极端精细  │ │   │
│ │  └───────────┴────────────────┴───────────────┴────────────┘ │   │
│ │                                                              │   │
│ │  采样 vs 插桩(Instrumentation)对比:                        │   │
│ │  ┌──────────────┬──────────────┬──────────────┬────────────┐ │   │
│ │  │ 特性          │ 采样(Sampling) │ 插桩(Instrumentation) │ │   │
│ │  ├──────────────┼──────────────┼──────────────┼────────────┤ │   │
│ │  │ 性能开销     │ 低            │ 高(每函数)    │            │ │   │
│ │  │ 精度         │ 近似(统计)    │ 精确(每调用)  │            │ │   │
│ │  │ 代码修改     │ 无            │ 需要          │            │ │   │
│ │  │ 适用场景     │ 生产环境      │ 开发调试      │            │ │   │
│ │  │ 支持语言     │ C/C++/汇编    │ Swift/OC/ASM  │            │ │   │
│ │  │ Swift支持    │ ✅ 符号化      │ ❌ 开销大     │            │ │   │
│ │  │ 异步调用     │ ✅ 自动追踪    │ 需手动追踪    │            │ │   │
│ │  └──────────────┴──────────────┴──────────────┴────────────┘ │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 采样数据的符号化过程:                                               │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │  原始地址 (0x1004AB123) → 无符号化                            │   │
│ │           ↓ 符号化 (symbolicate)                               │   │
│ │  函数名 (MyApp.MyClass.doSomething() + 0x42)                   │   │
│ │           ↓ 文件行号                                           │   │
│ │  MyApp.swift:42                                                │   │
│ │                                                                │   │
│ │  符号化依赖:                                                   │   │
│ │  • dSYM 文件(包含调试信息)                                    │   │
│ │  • 编译时的 DWARF 调试信息                                      │   │
│ │  • 运行时的符号表                                               │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

9.2 Time Profiler 火焰图解读

火焰图(Flame Graph)解读方法:

┌──────────────────────────────────────────────────────────────────────┐
│ 火焰图结构说明:                                                     │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │                                                              │ │
│  │  火焰图解读规则:                                              │ │
│  │                                                              │ │
│  │  • 横轴宽度 = 采样次数(越宽越耗时)                           │ │
│  │  • 纵轴深度 = 调用栈深度(从 main() 开始)                    │ │
│  │  • 每行一个函数                                              │ │
│  │  • 每个块是函数的调用片段                                      │ │
│  │  • 父块包含子块(从下往上调用)                                │ │
│  │                                                              │ │
│  │  火焰图示例:                                                  │ │
│  │                                                              │ │
│  │  ┌─────────────────────────────────────────────────────┐     │ │
│  │  │                    [main]                           │     │ │
│  │  │      ┌─────────────────────┐      ┌─────────────┐  │     │ │
│  │  │      │ [UIApplicationMain] │      │ [RunLoop]   │  │     │ │
│  │  │  ┌───┴──────────────────┐  │      └─────────────┘  │     │ │
│  │  │  │ [ViewController]     │  │                        │     │ │
│  │  │  │  ┌──────────────┐   │  │                        │     │ │
│  │  │  │  │ [tableView]  │   │  │                        │     │ │
│  │  │  │  │  ┌────────┐  │   │  │                        │     │ │
│  │  │  │  │  │cellFor│  │   │  │                        │     │ │
│  │  │  │  │  │RowAt]  │   │  │                        │     │ │
│  │  │  │  │  │  ┌───┐  │   │  │                        │     │ │
│  │  │  │  │  │  │... │  │   │  │                        │     │ │
│  │  │  │  │  │  └───┘  │   │  │                        │     │ │
│  │  │  │  │  └────────┘  │   │  │                        │     │ │
│  │  │  │  └──────────────┘   │  │                        │     │ │
│  │  │  └─────────────────────┘  │                        │     │ │
│  │  │                          │                          │     │ │
│  │  │  横轴宽度表示:采样次数 → 耗时                         │ │
│  │  └─────────────────────────────────────────────────────┘     │ │
│  │                                                              │ │
│  │  分析重点:                                                   │ │
│  │  ┌─────────────────────────────────────────────────────┐     │ │
│  │  │ 1. 最宽的柱子 → 耗时最长的函数(优先优化)            │     │ │
│  │  │ 2. 最左边的分支 → 调用入口点                         │     │ │
│  │  │ 3. 系统框架占比 → 占比过大需排查(如 UIKit 内部)     │     │ │
│  │  │ 4. 递归调用 → 检查是否有无限递归                      │     │ │
│  │  │ 5. 不在自己代码中的热点 → 可能是性能瓶颈               │     │ │
│  │  │ 6. 主线程 > 16ms → 卡顿(60fps 要求每帧 ≤ 16.67ms) │     │ │
│  │  └─────────────────────────────────────────────────────┘     │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                                                                      │
│  常见优化场景:                                                     │
│  ┌────────────────────────────────────────────────────────────────┐   │
│ │ 场景          │ 火焰图特征                  │ 优化方案           │   │
│ ├───────────────┼─────────────────────────────┼──────────────────┤   │
│ │ 列表渲染卡顿   │ cellForRow 最宽             │ 预计算/缓存        │   │
│ │ JSON 解析慢    │ JSONSerialization 最宽      │ 使用 Swift JSON    │   │
│ │ 图片加载慢     │ UIImage/CGImage 最宽        │ 异步加载/缓存      │   │
│ │ AutoLayout 慢  │ layoutSubviews 最宽         │ 减少约束/预布局    │   │
│ │ 字符串拼接慢   │ stringByAppending... 最宽   │ 使用 StringBuilder │   │
│ │ 网络请求同步   │ URLSession 在主线程         │ 异步 + Queue 切换  │   │
│ └───────────────┴─────────────────────────────┴──────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

9.3 Time Profiler 最佳实践

Time Profiler 最佳实践:

┌──────────────────────────────────────────────────────────────────────┐
│ 采样设置建议:                                                       │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ • 采样率:默认 1000Hz(一般场景足够)                            │   │
│ │ • 设备:优先 USB 真机(精度更高)                                │   │
│ │ • 开启 "Profile GPU":同时分析 GPU 性能                          │   │
│ │ • 关闭 "Instruments":减少额外开销                               │   │
│ │ • 预热运行:先跑几轮再开始记录                                    │   │
│ │ • 排除系统调用:勾选 "Profile GPU" 和 "Profile System Trace"    │   │
│ │ • 对比分析:优化后重新采样对比                                    │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 常见卡顿分析场景:                                                   │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 场景 1:列表滚动卡顿                                            │   │
│ │ 方法:Time Profiler + Core Animation 组合                      │   │
│ │ 定位:cellForRowAt 耗时 > 16ms → 优化 cell 配置                 │   │
│ │                                                              │   │
│ │ 场景 2:页面切换卡顿                                            │   │
│ │ 方法:Time Profiler + 查看 viewDidLoad 耗时                     │   │
│ │ 定位:大量计算在 viewDidLoad → 延迟加载                          │   │
│ │                                                              │   │
│ │ 场景 3:动画掉帧                                              │   │
│ │ 方法:Core Animation + Time Profiler                           │   │
│ │ 定位:离屏渲染 / 复杂 CALayer 动画                              │   │
│ │                                                              │   │
│ │ 场景 4:启动慢                                                │   │
│ │ 方法:Time Profiler + 记录启动全过程                            │   │
│ │ 定位:-application:didFinishLaunching: 中的耗时操作             │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

10. Allocations 内存分配追踪

10.1 Allocations 原理

Allocations 工具原理深度分析:

┌──────────────────────────────────────────────────────────────────────┐
│ Allocations 核心机制:                                               │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 实现原理:                                                      │   │
│ │                                                              │   │
│ │  1. hooks malloc/free/calloc/realloc/new/delete               │   │
│ │  2. 每次分配记录:                                             │   │
│ │     • 分配地址                                                  │   │
│ │     • 分配大小                                                  │   │
│ │     • 分配类型(NSObject / NSData / NSArray / ...)            │   │
│ │     • 调用栈(完整栈帧)                                        │   │
│ │     • 时间戳                                                    │   │
│ │     • 线程 ID                                                   │   │
│ │                                                              │   │
│  3. 释放时也记录(用于计算 Live Bytes)                             │   │
│  4. 通过快照(Snapshot)机制对比内存变化                            │   │
│                                                              │   │
│  内存分配记录结构:                                              │   │
│  ┌─────────────────────────────────────────────────────┐       │   │
│  │ struct AllocationRecord {                            │       │   │
│  │     void* address;       // 分配地址                  │       │   │
│  │     size_t size;         // 分配大小                  │       │   │
│  │     const char* type;    // 分配类型名                │       │   │
│  │     u_int32_t count;     // 计数                      │       │   │
│  │     void* stack[64];     // 调用栈                    │       │   │
│  │     u_int32_t stackDepth; // 栈深度                   │       │   │
│  │     thread_t thread;     // 分配线程                   │       │   │
│  │     double timestamp;    // 时间戳                    │       │   │
│  │ };                                                    │       │   │
│  └─────────────────────────────────────────────────────┘       │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ Allocations 核心指标:                                               │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 指标          │ 含义                           │ 分析要点      │   │
│ ├────────────────────────────────────────────────────────────────┤ │
│ │ Live Bytes    │ 当前活跃的内存总量             │ 持续增长=潜在 │   │
│ │               │                              │ 泄漏           │   │
│ │ Allocs        │ 对象分配次数                   │ 高频分配=性能  │   │
│ │               │                              │ 瓶颈           │   │
│ │ Bytes         │ 总分配字节数                   │ 分配总量       │   │
│ │ Refs          │ 引用计数                       │ 循环引用检测   │   │
│ │ Retained Size │ 对象及其引用链的总大小          │ 泄漏源头       │   │
│ │ Inactive Size │ 非活跃内存(可能即将释放)     │ GC 评估        │   │
│ │ Generation    │ 内存代数(分代追踪)          │ 短期vs长期对象  │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

10.2 Allocations 使用指南

Allocations 使用指南:

┌──────────────────────────────────────────────────────────────────────┐
│ 使用步骤:                                                           │
│                                                                      │
│  1. Open Instruments → Allocations                                   │
│  2. 选择设备/模拟器                                                 │
│  3. 点击 Record                                                      │
│  4. 执行测试场景                                                     │
│  5. 观察 Live Bytes 曲线                                             │
│  6. 使用 Snapshot 对比内存变化                                       │
│  7. 定位问题代码                                                     │
│                                                                      │
│  Snapshot 对比工作流程:                                             │
│  ┌────────────────────────────────────────────────────────────────┐   │
│ │  Step 1: 点击 "+" 按钮 → 创建 Snapshot A (基线)                │   │
│ │       ↓                                                        │   │
│ │  Step 2: 执行操作(如滑动列表 100 次)                           │   │
│ │       ↓                                                        │   │
│ │  Step 3: 点击 "+" 按钮 → 创建 Snapshot B                        │   │
│ │       ↓                                                        │   │
│ │  Step 4: 查看 A → B 的差异(Byte Increase)                     │   │
│ │       ↓                                                        │   │
│ │  Step 5: 按 Byte Increase 排序 → 找到增长最多的对象类型          │   │
│ │       ↓                                                        │   │
│ │  Step 6: 双击查看该类型的分配调用栈                              │   │
│ │       ↓                                                        │   │
│ │  Step 7: 定位到代码行 → 修复                                    │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 常见内存增长模式:                                                   │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 模式          │ 特征                          │ 原因           │   │
│ ├───────────────┼─────────────────────────────┼────────────────┤   │
│ │ 线性增长      │ Live Bytes 持续上升          │ 对象未释放     │   │
│ │ 阶梯增长      │ 增长→稳定→增长→稳定        │ 缓存未清理     │   │
│ │ 脉冲增长      │ 偶尔突增→恢复              │ 大对象分配     │   │
│ │ 周期性增长    │ 周期性上升                   │ 定时器/轮询    │   │
│ │ 视图控制器未释放 │ VC 实例数量持续增长     │ 循环引用       │   │
│ │ 数组无限增长  │ [AnyObject] 的 Count 持续增长  │ 缓存无上限     │   │
│ └───────────────┴─────────────────────────────┴────────────────┘   │
│                                                                      │
│ 分配类型分析技巧:                                                   │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ • 右键列 → 选择 "Only Show Heap" 排除系统分配                   │   │
│ │ • 右键列 → "Filter" → 输入类名过滤                              │   │
│ │ • 右键列 → "Sort By" → 按 Allocs/Bytes/Refs 排序               │   │
│ │ • 使用 "Generate Heap Snapshot" 对比时间点                       │   │
│ │ • 检查 "Retain Cycle" 检测(自动识别循环引用)                   │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

10.3 内存泄漏检测实战

内存泄漏检测实战:

┌──────────────────────────────────────────────────────────────────────┐
│ 内存泄漏检测流程图:                                                 │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │                                                                    │   │
│ │  1. 使用 Allocations 检测内存增长                              │   │
│ │     ↓                                                            │   │
│ │  2. 使用 Leaks 确认是否存在泄漏                                │   │
│ │     ↓                                                            │   │
│ │  3. 使用 Zombies 确认是否野指针                                │   │
│ │     ↓                                                            │   │
│ │  4. 定位泄漏代码                                               │   │
│ │     ↓                                                            │   │
│ │  5. 修复泄漏                                                   │   │
│ │     ↓                                                            │   │
│ │  6. 验证修复(再次 Profile 对比)                              │   │
│ │                                                                    │   │
│ 常见泄漏原因及修复方案:                                           │   │
│ ┌──────────────┬──────────────────────────┬───────────────────┐   │
│ │ 泄漏原因      │ 检测方式                  │ 修复方案          │   │
│ ├──────────────┼──────────────────────────┼───────────────────┤   │
│ │ 闭包循环引用 │ Allocations + Retain     │ [weak self]/      │   │
│ │              │ Cycle 检测                │ [unowned self]   │   │
│ │ NSTimer      │ Leaks                     │ timer.invalidate() │   │
│ │ NotificationCenter│ Allocations/Leaks  │ removeObserver    │   │
│ │ KVO          │ Allocations/Leaks       │ removeObserver    │   │
│ │ CADisplayLink │ Leaks                    │ invalidate()     │   │
│ │ Delegate     │ Retain Cycle 检测        │ weak delegate     │   │
│ │ 缓存无上限    │ Allocations 持续增长      │ 设置缓存上限       │   │
│ │ 通知/回调    │ Allocations               │ 清理注册           │   │
│ │ 定时器未取消  │ Leaks                     │ 统一清理机制       │   │
│ └──────────────┴──────────────────────────┴───────────────────┘   │
│                                                                      │
│ Swift 循环引用检测示例:                                             │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ // ❌ 泄漏 - 闭包循环引用                                      │   │
│ │ class MyViewController: UIViewController {                      │   │
│ │     override func viewDidLoad() {                               │   │
│ │         super.viewDidLoad()                                      │   │
│ │         Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) {  │   │
│ │             self.doSomething()  // 💥 self 被闭包捕获          │   │
│ │         }                                                        │   │
│ │     }                                                            │   │
│ │ }                                                                │   │
│ │                                                                │   │
│ │ // ✅ 修复 - weak self                                         │   │
│ │ class MyViewController: UIViewController {                      │   │
│ │     override func viewDidLoad() {                               │   │
│ │         super.viewDidLoad()                                      │   │
│ │         timer = Timer.scheduledTimer(withTimeInterval: 1.0,    │   │
│ │             repeats: true) { [weak self] _ in                  │   │
│ │             self?.doSomething()  // ✅ 安全                      │   │
│ │         }                                                        │   │
│ │     }                                                            │   │
│ │ }                                                                │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

11. Leaks 内存泄漏检测

11.1 Leaks 原理

Leaks 检测原理深度分析:

┌──────────────────────────────────────────────────────────────────────┐
│ Leaks 工具原理:                                                     │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 内存泄漏检测算法(标记-清除变体):                              │   │
│ │                                                              │   │
│ │  1. 分配标记阶段(Allocation Marking)                         │   │
│ │     • Instruments hooks malloc/free                           │   │
│ │     • 所有已分配内存被标记为 "已分配"                          │   │
│ │                                                              │   │
│ │  2. 根对象遍历阶段(Root Traversal)                           │   │
│ │     • 从根对象开始(全局变量、栈变量、寄存器)                   │   │
│ │     • 遍历所有引用链(retain/release 跟踪)                    │   │
│ │     • 所有可达对象被标记为 "可达"                              │   │
│ │                                                              │   │
│ │  3. 清除阶段(Sweeping)                                       │   │
│ │     • 已分配但未可达的对象 = 泄漏                              │   │
│ │     • 记录泄漏地址、大小、类型、调用栈                         │   │
│ │                                                              │   │
│ │  泄漏检测精度:                                                 │   │
│ │  ┌───────────────┬──────────────────────────────────────────┐ │   │
│ │  │ 检测能力       │ 精度                                     │ │   │
│ │  ├───────────────┼──────────────────────────────────────────┤ │   │
│ │  │ 完全泄漏       │ ✅ 100%(对象完全不可达)                 │ │   │
│ │  │ 部分泄漏       │ ✅ 90%+(至少部分不可达)                 │ │   │
│ │  │ 暂存泄漏       │ ❌ 可能误报(对象暂时无引用)             │ │   │
│ │  │ 延迟释放       │ ⚠️ 可能误报(对象将在下次循环释放)        │ │   │
│ │  │ ARC 对象       │ ✅ ARC 精确追踪                          │ │   │
│ │  │ CF 对象        │ ✅ Retain/Release 追踪                   │ │   │
│ │  │ malloc 内存    │ ✅ malloc/free 追踪                      │ │   │
│ │  └───────────────┴──────────────────────────────────────────┘ │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ Leaks 工作流程:                                                   │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │  1. 启动 Leaks 工具                                              │   │
│ │  2. 记录操作                                                     │   │
│ │  3. Instruments 自动检测泄漏(每 1 秒一次)                       │   │
│ │  4. 双击泄漏对象 → 查看调用栈                                     │   │
│ │  5. 定位泄漏代码                                                 │   │
│ │  6. 修复后重新验证                                               │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ Leaks 检测 vs ARC 自动内存管理:                                    │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 重要理解:                                                      │   │
│ │ • ARC 不等于没有内存泄漏!                                       │   │
│ │ • ARC 防止的是"过度释放",不防止"循环引用"                      │   │
│ │ • 循环引用 = 互相强引用 → 永远无法 dealloc                      │   │
│ │ • ARC 不会自动检测循环引用                                      │   │
│ │ • Leaks 工具检测的就是这种 ARC 无法解决的问题                   │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

11.2 常见泄漏场景详解

内存泄漏场景全解(含修复代码):

┌──────────────────────────────────────────────────────────────────────┐
│ 场景 1:闭包循环引用(最常见)                                       │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ // ❌ 泄漏:闭包捕获 self                                     │   │
│ │ class MyViewController: UIViewController {                      │   │
│ │     var completion: (() -> Void)?                              │   │
│ │     func fetchData() {                                           │   │
│ │         network.fetch { [self] data in  // 💥 循环引用!       │   │
│ │             self.updateUI(data)                                   │   │
│ │         }                                                        │   │
│ │     }                                                            │   │
│ │ }                                                                │   │
│ │                                                                │   │
│ │ // ✅ 修复:weak + unowned                                    │   │
│ │ func fetchData() {                                              │   │
│ │     network.fetch { [weak self] data in  // ✅ 强引用周期被打破 │   │
│ │         self?.updateUI(data)  // self 可能为 nil,安全          │   │
│ │     }                                                            │   │
│ │ }                                                                │   │
│ │                                                                │   │
│ │ // ✅ 更安全的写法:guard weak                                 │   │
│ │ func fetchData() {                                              │   │
│ │     network.fetch { [weak self] data in  // ✅                 │   │
│ │         guard let self = self else { return }                  │   │
│ │         self.updateUI(data)  // self 是确定的                   │   │
│ │     }                                                            │   │
│ │ }                                                                │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 场景 2:NSTimer 未 invalidate                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ // ❌ 泄漏:Timer 强引用 self                                  │   │
│ │ timer = Timer.scheduledTimer(                                  │   │
│ │     withTimeInterval: 1.0,                                      │   │
│ │     repeats: true,                                              │   │
│ │     target: self,  // 💥 self 被 Timer 强引用                 │   │
│ │     selector: #selector(update),                                │   │
│ │     userInfo: nil,                                              │   │
│ │     repeats: true                                               │   │
│ │ )                                                                │   │
│ │                                                                │   │
│ │ // ✅ 修复:使用 RunLoop + Block Timer                         │   │
│ │ timer = Timer.scheduledTimer(withTimeInterval: 1.0,           │   │
│ │     repeats: true) { [weak self] _ in  // ✅                 │   │
│ │     self?.update()                                               │   │
│ │ }                                                                │   │
│ │                                                                │   │
│ │ // ⚠️ 注意:viewWillDisappear 中仍需 invalidate               │   │
│ │ override func viewWillDisappear(_ animated: Bool) {            │   │
│ │     super.viewWillDisappear(animated)                            │   │
│ │     timer?.invalidate()                                          │   │
│ │     timer = nil                                                  │   │
│ │ }                                                                │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

11.3 更多泄漏场景

更多内存泄漏场景(续):

┌──────────────────────────────────────────────────────────────────────┐
│ 场景 3:NotificationCenter 未移除 Observer                            │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ // ❌ 泄漏:移除 Observer 的时机不对                            │   │
│ │ override func viewDidLoad() {                                   │   │
│ │     super.viewDidLoad()                                            │   │
│ │     NotificationCenter.default.addObserver(                     │   │
│ │         self,                                                    │   │
│ │         selector: #selector(didReceive),                        │   │
│ │         name: .MyEvent,                                          │   │
│ │         object: nil                                              │   │
│ │     )                                                            │   │
│ │ }                                                                │   │
│ │                                                                │   │
│ │ // ⚠️ 常见问题:                                                  │   │
│ │ • 在 dealloc 中移除 → ViewController 可能已经释放              │   │
│ │ • 忘记移除 → 永久泄漏                                           │   │
│ │                                                                │   │
│ │ // ✅ 修复:在合适的时机移除                                    │   │
│ │ override func viewWillDisappear(_ animated: Bool) {            │   │
│ │     super.viewWillDisappear(animated)                            │   │
│ │     NotificationCenter.default.removeObserver(self)             │   │
│ │ }                                                                │   │
│ │                                                                │   │
│ │ // ✅ 更安全的写法:                                              │   │
│ │ var notificationObserver: NSObjectProtocol?                      │   │
│ │ override func viewDidLoad() {                                   │   │
│ │     notificationObserver = NotificationCenter.default           │   │
│ │         .addObserver(forName: .MyEvent,                        │   │
│ │                        object: nil,                              │   │
│ │                        queue: .main) { [weak self] _ in         │   │
│ │             self?.didReceive()                                   │   │
│ │         }                                                        │   │
│ │ }                                                                │   │
│ │ deinit {                                                        │   │
│ │     if let observer = notificationObserver {                    │   │
│ │         NotificationCenter.default.removeObserver(observer)     │   │
│ │     }                                                            │   │
│ │ }                                                                │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 场景 4:KVO 未 removeObserver                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ // ❌ 泄漏:KVO Observer 未移除                                 │   │
│ │ override func viewDidLoad() {                                   │   │
│ │     observedObject.addObserver(                                  │   │
│ │         self,                                                    │   │
│ │         forKeyPath: "value",                                     │   │
│ │         options: [.new],                                         │   │
│ │         context: nil                                              │   │
│ │     )                                                            │   │
│ │ }                                                                │   │
│ │                                                                │   │
│ │ // ✅ 修复:确保配对使用                                       │   │
│ │ override func dealloc() {                                       │   │
│ │     observedObject.removeObserver(                                │   │
│ │         self,                                                    │   │
│ │         forKeyPath: "value"                                     │   │
│ │     )                                                            │   │
│ │ }                                                                │   │
│ │                                                                │   │
│ │ // ⚠️ 最佳实践:使用 KeyPath + 类型安全 API                     │   │
│ │ @objc dynamic var value: Int = 0                               │   │
│ │ observe(\.value, options: [.new]) { [weak self] obj, change in │   │
│ │     self?.handleValueChange(change.newValue)                     │   │
│ │ }                                                                │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 场景 5:CADisplayLink / NSURLConnection 未清理                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ // ❌ 泄漏:CADisplayLink 未 invalidate                        │   │
│ │ var displayLink: CADisplayLink?                                │   │
│ │ override func viewDidLoad() {                                   │   │
│ │     displayLink = CADisplayLink(target: self,                   │   │
│ │         selector: #selector(updateFrame))                       │   │
│ │     displayLink?.add(to: .main, forMode: .default)             │   │
│ │ }                                                                │   │
│ │                                                                │   │
│ │ // ✅ 修复:在适当时机 invalidate                               │   │
│ │ override func viewWillDisappear(_ animated: Bool) {            │   │
│ │     super.viewWillDisappear(animated)                            │   │
│ │     displayLink?.invalidate()                                    │   │
│ │     displayLink = nil                                            │   │
│ │ }                                                                │   │
│ │                                                                │   │
│ │ // ✅ 更安全的写法:                                             │   │
│ │ // 使用 weak self + guard 模式                                 │   │
│ │ displayLink = CADisplayLink(target: self,                      │   │
│ │     selector: #selector(updateFrame))                           │   │
│ │ displayLink?.add(to: .main, forMode: .default)                 │   │
│ │ deinit {                                                        │   │
│ │     displayLink?.invalidate()  // ✅ 在 dealloc 中清理          │   │
│ │ }                                                                │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

11.4 泄漏检测工具对比

内存泄漏检测工具对比:

┌──────────────────────────────────────────────────────────────────────┐
│ 工具           │ 检测能力           │ 精度    │ 性能开销 │ 适用阶段   │
├──────────────────────────────────────────────────────────────────────┤
│ Leaks          │ 完全/部分泄漏     │ 高      │ 低       │ 测试阶段   │
│ Allocations    │ 内存增长+泄漏     │ 中高    │ 中       │ 开发阶段   │
│ ASan           │ 使用后释放        │ 高      │ 高(2x-8x)│ 测试阶段   │
│ LeakCanary     │ Android 专用     │ 高      │ 低       │ Android   │
│ Xcode 内存图   │ 可视化内存布局    │ 中      │ 低       │ 调试阶段   │
│ AddressBook    │ 内存泄漏(实验性)  │ 高      │ 高       │ 测试阶段   │
│ 自定义 retain  │ 引用计数监控      │ 中      │ 低       │ 开发阶段   │
│ instrumentation │ 内存钩子         │ 高      │ 中       │ 生产分析   │
└──────────────────────────────────────────────────────────────────────┘

12. Zombies 悬垂指针检测

12.1 Zombies 原理

Zombies 工具原理:

┌──────────────────────────────────────────────────────────────────────┐
│ Zombies 工作原理:                                                   │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 工作原理:                                                      │   │
│ │                                                              │   │
│ │  正常对象生命周期:                                             │   │
│ │  创建 → retain → use → release → dealloc → 内存回收          │   │
│ │                                                              │   │
│ │  Zombies 模式:                                                │   │
│ │  创建 → retain → use → release → "zombie"(不死,改名)      │   │
│ │                                                              │   │
│ │  当 zombie 对象收到消息时:                                    │   │
│ │  ┌───────────────────────────────────────────────────────┐    │   │
│ │  │  1. 拦截 -retain/-release/-autorelease               │    │   │
│ │  │  2. release 时不 dealloc,改为:                      │    │   │
│ │  │     • 设置 isa 指向 _NSZombie_<ClassName>             │    │   │
│ │  │     • 保存原类名和原始地址                            │    │   │
│ │  │     • 将对象"复活"为僵尸对象                         │    │   │
│ │  │  3. 当 zombie 对象收到消息时:                        │    │   │
│ │  │     • 捕获 -forwardInvocation: 或 -methodSignatureForSelector: │
│ │  │     • 打印崩溃信息:                                  │    │   │
│ │  │       "Message sent to deallocated instance"          │    │   │
│ │  │       原对象类名、地址、创建/释放调用栈               │    │   │
│ │  └───────────────────────────────────────────────────────┘    │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ Zombies 与 ASan 对比:                                               │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 特性          │ Zombies               │ ASan                   │ │
│ ├────────────────────────────────────────────────────────────────┤ │
│ │ 检测内容      │ OC 对象使用后释放      │ 所有内存使用后释放      │ │
│ │ 适用语言      │ Objective-C            │ C/C++/Swift/OC        │ │
│ │ 性能开销      │ 低                     │ 高 (2x-8x)           │ │
│ │ 精确度        │ 中等(可能漏检)       │ 高                    │ │
│ │ 崩溃信息      │ 消息名 + 类名 + 地址    │ 精确的行号和调用栈     │ │
│ │ 生产可用      │ 否                     │ 否                    │ │
│ │ 检测时机      │ 运行时                 │ 运行时                │ │
│ │ 设置方式      │ NSZombieEnabled=YES     │ Xcode Scheme → ASan   │ │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 启用 Zombies:                                                       │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 方法 1: Xcode Scheme                                             │   │
│ │ Xcode → Product → Scheme → Diagnostics → Enable Zombies       │   │
│ │                                                                │   │
│ │ 方法 2: 环境变量                                                │   │
│ │ export NSZombieEnabled=YES                                      │   │
│ │ export NSAutoreleaseFreedObjectWriteTracking=YES              │   │
│ │                                                                │   │
│ │ 方法 3: launchctl                                              │   │
│ │ launchctl setenv NSZombieEnabled YES                            │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ Zombies 输出信息解读:                                               │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 典型输出:                                                      │   │
│ │ "*** -[MyClass doSomething]: message sent to deallocated       │   │
│ │  instance 0x600003fa0000"                                       │   │
│ │                                                                │   │
│ │ 解读:                                                        │   │
│ │ • MyClass 的实例 0x600003fa0000 已经被释放                     │   │
│ │ • 有人试图调用 doSomething 方法                                 │   │
│ │ • 修复:检查谁持有了这个对象的引用                              │   │
│ │ • 检查 delegate 是否置 nil                                     │   │
│ │ • 检查闭包是否捕获了 self                                      │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

13. Core Animation 渲染分析

13.1 Core Animation 架构

Core Animation 渲染机制:

┌──────────────────────────────────────────────────────────────────────┐
│ Core Animation 渲染管线:                                             │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │                                                              │   │
│ │  渲染管线:                                                   │   │
│ │                                                              │   │
│ │  Layer Tree (CPU)           →   Render Server (GPU)          │   │
│ │  ┌───────────────────┐              ┌──────────────────┐    │   │
│ │  │ UIView hierarchy  │  commit      │ CA::Transaction  │    │   │
│ │  │ (逻辑树)          │ ──────────→  │ (渲染事务)        │    │   │
│ │  │                  │              │                  │    │   │
│ │  │ • layout         │  render pass  │ • 几何变换       │    │   │
│ │  │ • content        │ ──────────→  │ • 色彩管理       │    │   │
│ │  │ • 变换           │              │ • 合成 (Compositing) │ │   │
│ │  │ • 阴影/圆角      │              │ • 栅格化          │    │   │
│ │  │ • 动画           │              │ • 优化 (Optimizing) │    │   │
│ │  └───────────────────┘              └──────────────────┘    │   │
│ │                                                              │   │
│ │  关键概念:                                                   │   │
│ │  • Commit:layerTree → RenderServer                         │   │
│ │  • Render Pass:将 layer 信息发给 GPU                         │   │
│ │  • Tiling:将屏幕分片(tiling)                              │   │
│ │  • Rasterization:光栅化(栅格化)                           │   │
│ │  • Display:显示到屏幕                                       │   │
│ │                                                              │   │
│ │  渲染时序(60fps = 16.67ms/帧):                            │   │
│ │  ┌──────────────────────────────────────────────────────┐    │   │
│ │  │  Layout (计算约束) → Render → Commit → Display → VSync │ │   │
│ │  │  0ms ────────────── 8ms ───── 10ms ──── 14ms ───── 16.67ms │ │   │
│ │  │                                                         │    │   │
│ │  │  关键:每帧必须在 16.67ms 内完成                         │    │   │
│ │  └──────────────────────────────────────────────────────┘    │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ Core Animation 常见性能问题:                                       │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 问题            │ 原因                    │ 解决方案          │   │
│ ├─────────────────┼─────────────────────────┼──────────────────┤   │
│ │ 离屏渲染       │ 圆角/shadow/clip         │ mipmap/自定义绘制 │   │
│ │ 过度栅格化     │ shouldRasterize=YES      │ 栅格化后缓存      │   │
│ │ 频繁重绘       │ contents 频繁变更        │ 缓存 contents     │   │
│ │ 复杂阴影       │ shadowPath 不设置        │ 设置 shadowPath   │   │
│ │ 大圆角         │ cornerRadius 大值        │ maskedCorners/    │   │
│ │                 │                         │ UIBezierPath      │   │
│ │ 不必要的动画   │ implicit animation       │ removeAllAnimations│   │
│ │ 图层层级过深   │ 嵌套 layer > 5 层       │ 扁平化 layer 树   │   │
│ │ 透明度过多     │ alpha < 1.0              │ 减少透明图层       │   │
│ └─────────────────┴─────────────────────────┴──────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

13.2 Core Animation 工具使用

Core Animation Instruments 使用:

┌──────────────────────────────────────────────────────────────────────┐
│ Core Animation 工具分析内容:                                       │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 指标            │ 含义                    │ 阈值             │   │
│ ├─────────────────┼─────────────────────────┼──────────────────┤   │
│ │ Tile Scale      │ 瓦片缩放比              │ ≤ 1.0(理想)    │   │
│ │ Offscreen Draws │ 离屏渲染次数            │ 0(理想)        │   │
│ │ Color Blended   │ 颜色混合次数            │ 越少越好         │   │
│ │ Shaded Rects    │ 阴影区域                │ 越少越好         │   │
│ │ Pixel Fill      │ 像素填充率              │ ≤ 1.0            │   │
│ │ Texture Upload  │ GPU 纹理上传            │ 越少越好         │   │
│ │ Texture Alloc   │ GPU 纹理分配            │ 0(理想)        │   │
│ │ Texture Resize  │ GPU 纹理重设            │ 越少越好         │   │
│ │ Core Image      │ CI 滤镜使用             │ 越少越好         │   │
│ │ Metal           │ Metal 调用              │ 越少越好         │   │
│ │ Swap Buffers    │ 缓冲区交换次数          │ = 帧数           │   │
│ │ Draw Calls      │ GPU 绘制调用            │ 越少越好         │   │
│ │ Layer Copies    │ 图层拷贝次数            │ 0(理想)        │   │
│ │ GPU Time        │ GPU 耗时                │ < 10ms/帧        │   │
│ │ Tile Time       │ 瓦片时间              │ < 8ms/帧         │   │
│ └─────────────────┴─────────────────────────┴──────────────────┘   │
│                                                                      │
│ Core Animation 最佳实践:                                           │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ • 避免离屏渲染:使用 CAShapeLayer + bezierPath                  │   │
│ │ • 减少阴影:使用预渲染的 shadowImage                            │   │
│ │ • 缓存渲染结果:cachedContext / shouldRasterize = YES(谨慎)  │   │
│ │ • 使用 CoreGraphics 自定义绘制(比系统视图更快)                │   │
│ │ • 减少透明图层:alpha < 1.0 触发混合                            │   │
│ │ • 预计算布局:缓存 layoutSubviews 结果                          │   │
│ │ • 使用 CADisplayLink 替代 Timer 做动画                          │   │
│ │ • 使用 CATransaction 批量更新(减少 commit 次数)               │   │
│ │ • 图片尺寸匹配屏幕(避免系统缩放)                              │   │
│ │ • 使用 UIGraphicsImageRenderer 替代 UIGraphicsBeginImageContext  │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

14. Network & Energy 工具

14.1 Network 工具

Network Instruments 工具:

┌──────────────────────────────────────────────────────────────────────┐
│ Network 工具分析内容:                                               │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 指标              │ 含义                    │ 关注点          │   │
│ ├───────────────────┼─────────────────────────┼─────────────────┤   │
│ │ Duration          │ 请求持续时间            │ > 1s 需优化     │   │
│ │ Data Sent         │ 发送数据量             │ 减少 payload    │   │
│ │ Data Received     │ 接收数据量             │ 压缩/分页       │   │
│ │ DNS Lookup        │ DNS 解析时间           │ CDN/本地缓存    │   │
│ │ TCP Connect       │ TCP 连接建立时间        │ 连接复用        │   │
│ │ TLS Handshake     │ TLS 握手时间           │ TLS 会话复用    │   │
│ │ Time to First Byte│ 首字节时间(TTFB)      │ 后端优化        │   │
│ │ Total Time        │ 总耗时                 │ < 200ms(理想)   │   │
│ │ Retry Count       │ 重试次数               │ 重试策略        │   │
│ │ Error Count       │ 错误次数               │ 错误处理        │   │
│ │ Cache Status      │ 缓存状态              │ 缓存命中率      │   │
│ │ Protocol          │ 协议版本              │ HTTP/2 vs HTTP/1 │  │
│ │ IP Address        │ 服务器地址            │ 就近访问        │   │
│ │ SSL Certificate   │ SSL 证书信息           │ 证书有效性      │   │
│ └───────────────────┴─────────────────────────┴─────────────────┘   │
│                                                                      │
│ Network 工具使用技巧:                                               │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ • 使用 "Network Link Conditioner" 模拟弱网                     │   │
│ │ • 使用 "Slow Motion Network" 慢速网络模拟                      │   │
│ │ • 关注重定向链(减少重定向次数)                               │   │
│ │ • 检查 HTTP 缓存头(Cache-Control, ETag)                       │   │
│ │ • 使用 gzip/brotli 压缩                                        │   │
│ │ • 启用 HTTP/2 多路复用                                         │   │
│ │ • 连接池(Keep-Alive)减少握手开销                              │   │
│ │ • 使用 CDN 加速静态资源                                        │   │
│ │ • 图片 WebP 格式 + 懒加载                                      │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

14.2 Energy Log 工具

Energy Log Instruments 工具:

┌──────────────────────────────────────────────────────────────────────┐
│ Energy Log 能耗分析:                                                │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 能耗维度:                                                      │   │
│ │                                                              │   │
│ │  CPU Energy:CPU 能耗                                          │   │
│ │  • 频率调整(P-State):频率越高能耗越大                        │   │
│ │  • 核心数:使用更多核心 = 更高能耗                              │   │
│ │  • 空闲 vs 活跃:空闲时能耗极低                                │   │
│ │                                                              │   │
│ │  GPU Energy:GPU 能耗                                          │   │
│ │  • 渲染复杂度:三角形数量/纹理大小                             │   │
│ │  • 着色器复杂度:指令数                                       │   │
│ │  • 像素填充率:Overdraw 越多能耗越大                            │   │
│ │                                                              │   │
│ │  Network Energy:网络能耗                                      │   │
│ │  • 传输数据量:数据量越大能耗越大                              │   │
│ │  • 信号强度:信号越弱能耗越大                                  │   │
│ │  • 协议:HTTP/2 比 HTTP/1 能耗更低                            │   │
│ │                                                              │   │
│ │  Wi-Fi / Bluetooth Energy:                                    │   │
│ │  • 连接状态:连接中 vs 空闲                                    │   │
│ │  • 数据传输频率                                                │   │
│ │                                                              │   │
│ │  Disk Energy:磁盘能耗                                         │   │
│ │  • 读写频率:频繁读写 = 高能耗                                 │   │
│ │  • 数据量                                                    │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 能耗优化建议:                                                       │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ • 减少后台任务频率                                                │   │
│ │ • 使用 Core Location 的 significantChange 代替频繁定位            │   │
│ │ • 减少网络请求频率                                                │   │
│ │ • 批量处理数据                                                   │   │
│ │ • 使用 NSUrlConnection 的缓存                                    │   │
│ │ • 减少 CPU 密集型操作(压缩/加密/计算)                          │   │
│ │ • 使用 Metal 替代 CoreGraphics(GPU 加速)                       │   │
│ │ • 减少 AutoLayout 约束数量                                       │   │
│ │ • 使用 CADisplayLink 而非 Timer 做动画                           │   │
│ │ • 减少透明图层(触发混合计算)                                    │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

15. System Trace 系统级追踪

15.1 System Trace 原理

System Trace(系统级追踪)原理:

┌──────────────────────────────────────────────────────────────────────┐
│ System Trace 工具:                                                  │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 追踪范围:                                                      │   │
│ │                                                              │   │
│ │  内核层面:                                                    │   │
│ │  • 调度(Scheduling):进程/线程切换                           │   │
│ │  • 内存管理:page fault / swap                               │   │
│ │  • I/O:磁盘/网络/蓝牙 I/O                                    │   │
│ │  • 电源管理:电源状态变化                                      │   │
│ │  • Mach 端口:进程间通信                                       │   │
│ │  • 文件系统:VFS 调用                                          │   │
│ │                                                              │   │
│ │  用户态层面:                                                  │   │
│ │  • dyld 加载                                                  │   │
│ │  • 框架调用(UIKit/Foundation 等)                            │   │
│ │  • 信号处理                                                   │   │
│ │  • 系统调用                                                   │   │
│ │                                                              │   │
│ │  使用场景:                                                    │   │
│ │  • 启动时间分析(launch time)                                │   │
│ │  • 死锁/饥饿分析                                              │   │
│ │  • I/O 性能分析                                               │   │
│ │  • 系统事件关联                                               │   │
│ │  • 框架性能分析                                               │   │
│ │                                                              │   │
│ │  与 Time Profiler 对比:                                       │   │
│ │  ┌────────────────┬─────────────────┬──────────────────────┐ │   │
│ │  │ 维度           │ System Trace    │ Time Profiler        │ │   │
│ │  ├────────────────┼─────────────────┼──────────────────────┤ │   │
│ │  │ 范围           │ 全系统          │ 仅用户态(进程)     │ │   │
│ │  │ 粒度           │ 事件级          │ 采样级               │ │   │
│ │  │ 开销           │ 高              │ 低                   │ │   │
│ │  │ 记录时长       │ 短时(秒级)    │ 长时(分钟级)       │ │   │
│ │  │ 系统事件       │ ✅              │ ❌                   │ │   │
│ │  │ 进程间通信     │ ✅              │ ❌                   │ │   │
│ │  │ 内核调度       │ ✅              │ ❌                   │ │   │
│ │  │ 文件 I/O       │ ✅              │ ❌                   │ │   │
│ │  │ 帧渲染         │ ✅              │ ⚠️ 间接              │ │   │
│ │  │ 使用复杂度     │ 高              │ 低                   │ │   │
│ │  └────────────────┴─────────────────┴──────────────────────┘ │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ System Trace 输出解读:                                              │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 主要事件类型:                                                 │   │
│ │ • thread_switch → 线程切换                                    │   │
│ │ • mach_msg_send/receive → IPC 消息                            │   │
│ │ • io_write/read → 磁盘 I/O                                    │   │
│ │ • network_* → 网络事件                                        │   │
│ │ • vnodes_* → 文件系统事件                                     │   │
│ │ • com_apple_Mach_exception → 异常事件                         │   │
│ │ • com_apple_mach_exc_server → Mach 异常服务器                 │   │
│ │ • kern_task_suspend/resume → 进程挂起/恢复                    │   │
│ │ • dispatch_async/async_work → GCD 事件                        │   │
│ │ • CA::transaction → Core Animation 事务                       │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

16. 模拟器调试

16.1 Simulator 调试功能

模拟器调试功能全景:

┌──────────────────────────────────────────────────────────────────────┐
│ 模拟器调试功能一览:                                                 │
│                                                                      │
│ ┌─────────────────────┬──────────────────────┬───────────────────┐  │
│ │ 功能                │ 操作方式             │ 调试场景          │  │
│ ├─────────────────────┼──────────────────────┼───────────────────┤  │
│ │ 旋转设备            │ ⌘ + ←/→            │ 横竖屏适配        │  │
│ │ 缩放                │ ⌘ + +/−            │ 响应式布局        │  │
│ │ 模拟来电            │ Features → Simulate  │ 电话功能测试      │  │
│ │ 模拟短信            │   Incoming Call      │ SMS 功能测试      │  │
│ │ 模拟锁屏            │ ⌘ + ⌥ + E          │ 锁屏/唤醒流程     │  │
│ │ 模拟 GPS 位置       │ Features → Location  │ LBS 功能测试      │  │
│ │ 模拟摇晃撤销        │ ⌘ + ←               │ 撤销功能测试      │  │
│ │ 慢速网络            │ Network Link         │ 弱网测试          │  │
│ │ GPU Frame Capture   │ ⌘ + G              │ Metal 帧分析      │  │
│ │ GPU Driver Debug    │ GPU Frame Capture    │ Metal 驱动调试    │  │
│ │ 内存压力模拟        │ ⌘ + M               │ 内存不足场景      │  │
│ │ 低电量模拟          │ Features → Battery   │ 低电量处理        │  │
│ │ 多任务界面          │ ⌘ + Shift + H       │ App 切换测试      │  │
│ │ 截屏                │ ⌘ + S               │ UI 截图           │  │
│ │ 录屏                │ Features → Record      │ 屏幕录制          │  │
│ │ WiFi 模拟           │ Features → WiFi      │ WiFi 连接测试     │  │
│ │ 蓝牙模拟            │ Features → Bluetooth  │ 蓝牙连接测试      │  │
│ └─────────────────────┴──────────────────────┴───────────────────┘  │
│                                                                      │
│ Simulator 网络调试:                                                 │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ Network Link Conditioner(网络链接调节器):                    │   │
│ │                                                              │   │
│ │  1. Xcode → Window → Devices and Simulators                  │   │
│ │  2. 选择模拟器 → 点击 "Show Network Link Conditioner"        │   │
│ │                                                              │   │
│ │  预设配置:                                                   │   │
│ │  • No Loss (理想网络)                                          │   │
│ │  • Good 3G                                                    │   │
│ │  • Bad 3G                                                     │   │
│ │  • Dialup                                                     │   │
│ │  • Custom (自定义延迟/带宽/丢包率)                             │   │
│ │                                                              │   │
│ │  可调参数:                                                   │   │
│ │  • Upload/Download Bandwidth (带宽)                           │   │
│ │  • Upload/Download Latency (延迟)                              │   │
│ │  • Upload/Download Packet Loss (丢包率)                       │   │
│ │  • Upload/Download Jitter (抖动)                               │   │
│ │  • Packet Corruption (数据包损坏)                              │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

16.2 Simulator 与真机调试差异

模拟器 vs 真机调试差异:

┌──────────────────────────────────────────────────────────────────────┐
│ 模拟器 vs 真机对比:                                                 │
│                                                                      │
│ ┌───────────────────┬──────────────────┬───────────────────────┐   │
│ │ 维度              │ Simulator         │ Real Device          │   │
│ ├───────────────────┼──────────────────┼───────────────────────┤   │
│ │ 处理器            │ x86_64 / ARM64   │ ARM64                │   │
│ │ 架构模拟          │ x86→ARM 二进制   │ 原生 ARM             │   │
│ │                   │   转换(性能损失)  │                      │   │
│ │ 性能              │ 较快(无硬件限制)│ 真实性能              │   │
│ │ 网络              │ WiFi 模拟        │ 真实网络(3G/4G/5G)  │   │
│ │ 传感器            │ 模拟             │ 真实传感器            │   │
│ │ GPS               │ 模拟             │ 真实 GPS             │   │
│ │ 相机              │ 模拟             │ 真实相机             │   │
│ │ 蓝牙              │ 模拟             │ 真实蓝牙             │   │
│ │ 内存              │ 宿主机器内存     │ 设备物理内存          │   │
│ │ 电池              │ 模拟             │ 真实电池              │   │
│ │ 温度              │ 无               │ 真实温度             │   │
│ │ 崩溃率            │ 低               │ 真实崩溃率            │   │
│ │ App Store 审核    │ 不适用           │ 适用                  │   │
│ │ Metal GPU 调试    │ 有限支持         │ 完整支持              │   │
│ │ 推送通知          │ 模拟             │ 真实推送              │   │
│ │ 钥匙串            │ 模拟             │ 真实钥匙串            │   │
│ │ 定位              │ 模拟             │ 真实定位              │   │
│ │ 性能数据准确性    │ 参考性           │ 真实性                │   │
│ └───────────────────┴──────────────────┴───────────────────────┘   │
│                                                                      │
│ 调试策略建议:                                                       │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ • 开发阶段:模拟器快速迭代                                     │   │
│ │ • 功能测试:真机验证关键功能                                     │   │
│ │ • 性能测试:真机测试(模拟器性能不代表真机)                    │   │
│ │ • 网络测试:真机 + Network Link Conditioner                    │   │
│ │ • 内存测试:真机(模拟器内存不代表真机)                        │   │
│ │ • Metal GPU 测试:真机(模拟器 Metal 支持有限)                 │   │
│ │ • 崩溃复现:真机(模拟器崩溃不代表真机会崩溃)                  │   │
│ │ • 功耗测试:真机(模拟器无功耗概念)                            │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

17. 崩溃日志分析

17.1 崩溃日志符号化

崩溃日志符号化流程深度分析:

┌──────────────────────────────────────────────────────────────────────┐
│ 崩溃符号化原理:                                                     │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 崩溃日志结构:                                                  │   │
│ │                                                              │   │
│ │  ┌─────────────────────────────────────────────────────┐     │   │
│ │  │ 崩溃报告头部                                             │     │   │
│ │  │  • 崩溃时间、设备型号、iOS 版本                         │     │   │
│ │  │  • UUID(二进制文件标识)                               │     │   │
│ │  │  • 崩溃类型(EXC_BAD_ACCESS 等)                       │     │   │
│ │  └─────────────────────────────────────────────────────┘     │   │
│ │                                                              │   │
│ │  ┌─────────────────────────────────────────────────────┐     │   │
│ │  │ 调用栈(Exception Type / Exception Codes)             │     │   │
│ │  │  • 崩溃线程(thread N)                               │     │   │
│ │  │  • 堆栈帧(0x... → symbol + offset)                  │     │   │
│ │  │  • 寄存器状态                                         │     │   │
│ │  │  • VM 区域映射(VM Region)                           │     │   │
│ │  └─────────────────────────────────────────────────────┘     │   │
│ │                                                              │   │
│ │  符号化依赖:                                                  │   │
│ │  • dSYM 文件(包含 DWARF 调试信息)                            │   │
│ │  • UUID 匹配(崩溃日志 UUID = dSYM UUID)                     │   │
│ │  • symbolicatecrash 工具                                     │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 符号化方法:                                                         │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 方法 1: Xcode 内符号化                                          │   │
│ │ Xcode → Window → Devices and Simulators                         │   │
│ │ → 选择设备 → View Device Logs → 选择崩溃报告 → View Report     │   │
│ │                                                                │   │
│ │ 方法 2: 命令行符号化                                            │   │
│ │ symbolicatecrash crash.crash MyApp.app.dSYM > symbolicated.crash │   │
│ │                                                              │   │
│ │ 方法 3: Xcode Organizer                                        │   │
│ │ Xcode → Window → Organizer → Crashes                           │   │
│ │ → 选择崩溃 → Symbolicate                                        │   │
│ │                                                              │   │
│ │ 方法 4:第三方工具                                              │   │
│ │ • CrashReporter (GitHub)                                       │   │
│ │ • pycrashreport (Python)                                       │   │
│ │ • symbolicatecrash (Xcode 内置)                                │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ dSYM 文件说明:                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ dSYM(Debug Symbols):                                         │   │
│ │ • 包含 DWARF 调试信息                                             │   │
│ │ • 与二进制文件一一对应(UUID 绑定)                               │   │
│ │ • 存储位置:~/Library/Developer/Xcode/Archives/                 │   │
│ │ • 归档中的 dSYM:MyApp.xcarchive/dSYMs/                         │   │
│ │ • 从归档提取:xcrun dSYMSummary MyApp.xcarchive                 │   │
│ │ • 检查 dSYM UUID:dwarfdump --uuid MyApp.app.dSYM              │   │
│ │ • 检查崩溃日志 UUID:UUIDs 部分匹配                              │   │
│ │                                                              │   │
│ │ 重要:dSYM 必须妥善保存!                                       │   │
│ │ • 发布版本必须保留 dSYM                                         │   │
│ │ • 丢失 dSYM = 无法符号化崩溃报告                                │   │
│ │ • 使用 Xcode Archive 自动保存                                  │   │
│ │ • 使用 fastlane/sigh 自动管理 dSYM                             │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

17.2 崩溃类型详解

崩溃类型深度分析:

┌──────────────────────────────────────────────────────────────────────┐
│ 常见崩溃类型及修复方案:                                             │
│                                                                      │
│ ┌────────────────┬──────────────────────┬───────────────────────┐  │
│ │ 崩溃类型       │ 原因                 │ 修复方案              │  │
│ ├────────────────┼──────────────────────┼───────────────────────┤  │
│ │ EXC_BAD_ACCESS │ 野指针/释放后使用    │ 检查所有权/weak       │  │
│ │                │                      │ ASan 检测             │  │
│ │                │                      │ Zombies 检测          │  │
│ │                │                      │ 检查 dealloc          │  │
│ │                │                      │ 检查 delegate         │  │
│ │                │                      │ 检查闭包循环引用      │  │
│ │                │                      │                       │  │
│ │ EXC_CRASH      │ 未捕获异常/SIGKILL   │ 检查 NSException      │  │
│ │                │                      │ 检查 uncaughtException│  │
│ │                │                      │ 检查 SIGKILL 原因      │  │
│ │                │                      │ (内存不足/超时)        │  │
│ │                │                      │                       │  │
│ │ EXC_ARITHMETIC │ 除以零/整数溢出      │ 安全检查              │  │
│ │                │                      │ 使用 checked 操作      │  │
│ │                │                      │ 范围检查               │  │
│ │                │                      │                       │  │
│ │ EXC_BREAKPOINT │ breakpoint/断言失败  │ 条件检查              │  │
│ │                │                      │ 移除调试断点          │  │
│ │                │                      │ 安全检查断言          │  │
│ │                │                      │                       │  │
│ │ SIGABRT        │ uncaughtException    │ 异常处理              │  │
│ │                │                      │ 检查 JSON 解析        │  │
│ │                │                      │ 检查参数有效性         │  │
│ │                │                      │                       │  │
│ │ SIGSEGV        │ 数组越界/内存越界    │ ASan 检测             │  │
│ │                │                      │ 边界检查               │  │
│ │                │                      │ 检查指针运算           │  │
│ │                │                      │                       │  │
│ │ SIGBUS         │ 对齐错误/内存映射    │ 检查内存对齐           │  │
│ │                │                      │ 检查 mmap             │  │
│ │                │                      │                       │  │
│ │ SIGILL         │ 非法指令             │ 检查字节序             │  │
│ │                │                      │ 检查汇编代码           │  │
│ │                │                      │                       │  │
│ │ KERN_PROTECTION│ 内存访问权限         │ 检查权限位             │  │
│ │                │                      │ 检查 mprotect         │  │
│ │                │                      │                       │  │
│ └────────────────┴──────────────────────┴───────────────────────┘  │
│                                                                      │
│ EXC_BAD_ACCESS 深度分析:                                            │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ EXC_BAD_ACCESS 子类型:                                          │   │
│ │ • KERN_INVALID_ADDRESS → 无效地址(野指针)                    │   │
│ │ • KERN_PROTECTION_FAILURE → 权限不足                           │   │
│ │ • EXC_ARM_DA_ALIGN → 未对齐访问                                │   │
│ │                                                                │   │
│ │ 常见原因:                                                      │   │
│ │ 1. 释放后使用(use-after-free)                                │   │
│ │ 2. 野指针(悬垂指针)                                          │   │
│ │ 3. 数组越界                                                    │   │
│ │ 4. 未初始化指针                                                │   │
│ │ 5. 内存越界                                                    │   │
│ │ 6. 访问已释放的内存                                            │   │
│ │ 7. 多线程数据竞争                                              │   │
│ │                                                                │   │
│ │ 排查方法:                                                      │   │
│ │ • ASan → 精确定位                                               │   │
│ │ • Zombies → 确定释放时间                                        │   │
│ │ • TSan → 检查数据竞争                                           │   │
│ │ • 崩溃报告调用栈 → 定位崩溃位置                                 │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

17.3 崩溃报告解析

崩溃报告完整解析:

┌──────────────────────────────────────────────────────────────────────┐
│ 崩溃报告(.crash 文件)解析:                                       │
│                                                                      │
│ 崩溃报告结构:                                                       │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 1. 头部信息(OS Version / Device Model / Date/Time)           │   │
│ │ 2. 崩溃类型(Exception Type / Codes)                           │   │
│ │ 3. 崩溃线程(thread N Crashed)                                 │   │
│ │ 4. 调用栈(Binary Images / VM Regions)                         │   │
│ │ 5. 寄存器状态(All Registers / Native)                          │   │
│ │ 6. 二进制镜像列表(Binary Images / UUID 匹配)                  │   │
│ │ 7. VM 区域映射(VM Region Summary)                             │   │
│ │ 8. 扩展信息(Incident Identifier / CrashReporter Key)          │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 调用栈分析步骤:                                                     │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 步骤 1: 定位崩溃线程                                            │   │
│ │ Thread N Crashed                                              │   │
│ │   0  MyApp 0x0000000100abc123 MyClass.method + 123            │   │
│ │   1  MyApp 0x0000000100def456 MyClass.otherMethod + 88        │   │
│ │   2  MyApp 0x0000000100123789 MyClass.anotherMethod + 45      │   │
│ │   ...                                                          │   │
│ │                                                                │   │
│ │ 步骤 2: 符号化调用栈                                             │   │
│ │ 0  MyClass.method(MyClass.swift:42)  ← 崩溃点                  │   │
│ │ 1  MyClass.otherMethod(MyClass.swift:100)                     │   │
│ │ 2  MyClass.anotherMethod(MyClass.swift:200)                   │   │
│ │                                                                │   │
│ │ 步骤 3: 分析崩溃原因                                            │   │
│ │ • 检查崩溃行代码                                                │   │
│ │ • 检查该行的变量状态                                             │   │
│ │ • 检查调用链中的错误传播                                         │   │
│ │ • 检查资源释放时机                                               │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 崩溃报告中的 Binary Images 解析:                                    │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ Binary Images:                                                  │   │
│ │ 0x100000000 - 0x100ffffff  MyApp arm64  <UUID>  MyApp.app    │   │
│ │ 0x180000000 - 0x1801fffff  UIKit arm64  <UUID>  /usr/lib/... │   │
│ │ 0x1a0000000 - 0x1a05fffff  libswiftCore.dylib                 │   │
│ │ ...                                                            │   │
│ │                                                                │   │
│ │ 用途:                                                         │   │
│ │ • UUID 匹配 dSYM 文件                                          │   │
│ │ • 确定崩溃发生在哪个模块                                        │   │
│ │ • 区分框架代码 vs 自身代码                                      │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

18. Sanitizer 运行时检测

18.1 Address Sanitizer (ASan)

ASan 原理深度分析:

┌──────────────────────────────────────────────────────────────────────┐
│ Address Sanitizer (ASan) 原理:                                     │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ ASan 工作原理:                                                │   │
│ │                                                              │   │
│ │  1. 编译期插桩:                                             │   │
│ │     • 在每个 malloc/free/new/delete 周围插入检查代码           │   │
│ │     • 在每个内存访问(load/store)周围插入检查代码              │   │
│ │     • 在每个函数调用周围插入 red zone 检查                      │   │
│ │                                                              │   │
│  2. 运行时检测:                                               │   │
│ │     • malloc/free 时修改内存页权限(shadow memory)             │   │
│ │     • 内存访问时检查 shadow memory                            │   │
│ │     • 发现越界/使用后释放时触发崩溃                             │   │
│ │                                                              │   │
│ │  Shadow Memory(阴影内存):                                  │   │
│ │  • 每 8 字节的用户内存对应 1 字节的 shadow memory              │   │
│ │  • Shadow 值含义:                                            │   │
│ │    • 0 → 可访问的内存                                         │   │
│ │    • 1-127 → 剩余的字节数(部分可用)                         │   │
│ │    • 128-251 → 已释放的堆内存                                 │   │
│ │    • 252-253 → 已释放的栈内存                                 │   │
│ │    • 254 → 已释放的全局/静态内存                              │   │
│ │    • 255 → 红色区域(guard zone)                             │   │
│ │                                                              │   │
│ │ ASan 检测的错误类型:                                          │   │
│ │  ┌──────────────────────────────────────────────────────┐    │   │
│ │  │ • 堆使用后释放 (heap-use-after-free)               │    │   │
│ │  │ • 栈使用后释放 (stack-use-after-return)             │    │   │
│ │  │ • 全局使用后释放 (global-use-after-free)            │    │   │
│ │  │ • 堆越界写 (heap-buffer-overflow)                  │    │   │
│ │  │ • 堆越界读 (heap-buffer-overflow read)             │    │   │
│ │  │ • 栈越界 (stack-buffer-overflow)                   │    │   │
│ │  │ • 全局越界 (global-buffer-overflow)                │    │   │
│ │  │ • 重复释放 (double-free)                           │    │   │
│ │  │ • 内存泄漏 (leak - 需要 LeakSanitizer)             │    │   │
│ │  │ • 初始化顺序 (init-order)                          │    │   │
│ │  │ • 比较大小 (sizeof-compare)                        │    │   │
│ │  └──────────────────────────────────────────────────────┘    │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ ASan 启用与配置:                                                   │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 启用方式:                                                     │   │
│ │ Xcode → Scheme → Diagnostics → Enable Address Sanitizer       │   │
│ │                                                              │   │
│ │ 环境变量配置:                                                 │   │
│ │ ASAN_OPTIONS=detect_stack_use_after_return=1                  │   │
│ │ ASAN_OPTIONS=detect_leaks=1                                   │   │
│ │ ASAN_OPTIONS=print_stats=1                                    │   │
│ │ ASAN_OPTIONS=check_initialization_order=1                     │   │
│ │ ASAN_OPTIONS=strict_string_checks=1                           │   │
│ │ ASAN_OPTIONS=detect_odr_violation=1                           │   │
│ │ ASAN_OPTIONS=halt_on_error=1                                  │   │
│ │ ASAN_OPTIONS=symbolize=1                                      │   │
│ │ ASAN_OPTIONS=verbosity=1                                      │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ ASan 性能开销:                                                     │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 指标            │ 开销                                         │   │
│ ├─────────────────┼──────────────────────────────────────────────┤   │
│ │ CPU 开销        │ 2x-8x(取决于检测类型)                      │   │
│ │ 内存开销        │ 2x(shadow memory)                          │   │
│ │ 启动延迟        │ 较高(初始检测)                               │   │
│ │ 崩溃概率        │ 高(覆盖所有内存错误)                        │   │
│ │ 检测精度        │ 高(精确到字节)                              │   │
│ │ 误报率          │ 极低                                          │   │
│ │ 适用场景        │ 开发/测试阶段                                 │   │
│ │ 生产可用        │ 否                                           │   │
│ └─────────────────┴──────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

18.2 Thread Sanitizer (TSan)

Thread Sanitizer (TSan) 原理:

┌──────────────────────────────────────────────────────────────────────┐
│ Thread Sanitizer (TSan) 原理:                                       │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ TSan 工作原理:                                                │   │
│ │                                                              │   │
│ │  1. 编译期插桩:                                             │   │
│ │     • 在每个锁操作(pthread_mutex_lock/unlock)周围插入代码    │   │
│ │     • 在每个内存读写操作周围插入代码                           │   │
│ │     • 在每个线程创建/销毁周围插入代码                          │   │
│ │                                                              │   │
│ │  2. 运行时检测:                                             │   │
│ │     • 维护 Happens-Before 关系图                              │   │
│ │     • 检测数据竞争(Data Race)                               │   │
│ │     • 检测锁顺序违反(Lock Order)                            │   │
│ │     • 检测锁释放后访问(Lock After Unlock)                   │   │
│ │                                                              │   │
│ │  TSan 检测的问题类型:                                       │   │
│ │  ┌──────────────────────────────────────────────────────┐    │   │
│ │  │ • 数据竞争 (Data Race)                              │    │   │
│ │  │   → 多个线程同时访问同一内存,至少一个是写操作          │    │   │
│ │  │ • 锁顺序违反 (Lock Order Violation)                 │    │   │
│ │  │   → 锁 A 和锁 B 以不同顺序获取 → 死锁风险             │    │   │
│ │  │ • 锁释放后访问 (Lock After Unlock)                  │    │   │
│ │  │   → 解锁后仍然访问被锁保护的内存                        │    │   │
│ │  │ • 释放后获取 (Acquire After Release)               │    │   │
│ │  │   → 先 unlock 再 lock 同一锁                           │    │   │
│ │  │ • 内存泄漏 (Memory Leak - 部分支持)                │    │   │
│ │  └──────────────────────────────────────────────────────┘    │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ TSan 启用与配置:                                                   │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 启用方式:                                                     │   │
│ │ Xcode → Scheme → Diagnostics → Enable Thread Sanitizer       │   │
│ │                                                              │   │
│ │ 常见数据竞争场景:                                              │   │
│ │ // ❌ 数据竞争:两个 Task 同时访问非线程安全的数组              │   │
│ │ let shared = MySharedObject()                                 │   │
│ │ Task {                                                        │   │
│ │     shared.data.append("A")  // 可能数据竞争                  │   │
│ │ }                                                              │   │
│ │ Task {                                                        │   │
│ │     shared.data.append("B")  // 可能数据竞争                  │   │
│ │ }                                                              │   │
│ │                                                              │   │
│ │ // ✅ 修复:用 Actor 保证线程安全                              │   │
│ │ actor SharedData {                                           │   │
│ │     var data: [String] = []                                   │   │
│ │     func append(_ s: String) { data.append(s) }              │   │
│ │ }                                                              │   │
│ │                                                              │   │
│ │ // ✅ 修复:用 DispatchQueue 串行化                            │   │
│ │ let queue = DispatchQueue(label: "com.app.shared")           │   │
│ │ queue.async { self.data.append("A") }                        │   │
│ │ queue.async { self.data.append("B") }                        │   │
│ │                                                              │   │
│ │ // ✅ 修复:用 os_unfair_lock                                  │   │
│ │ var lock = os_unfair_lock()                                   │   │
│ │ os_unfair_lock(&lock)                                        │   │
│ │ self.data.append("A")                                         │   │
│ │ os_unfair_unlock(&lock)                                       │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ TSan 性能开销:                                                     │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 指标            │ 开销                                         │   │
│ ├─────────────────┼──────────────────────────────────────────────┤   │
│ │ CPU 开销        │ 10x-15x(较高)                              │   │
│ │ 内存开销        │ 2x-4x(追踪表)                               │   │
│ │ 启动延迟        │ 较高                                          │   │
│ │ 检测精度        │ 高(基于 Happens-Before)                    │   │
│ │ 误报率          │ 低(TSan 设计减少了误报)                    │   │
│ │ 适用场景        │ 开发/测试阶段                                 │   │
│ │ 生产可用        │ 否                                           │   │
│ └─────────────────┴──────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

18.3 UBSan 与 ASan/TSan 对比

UBSan 与 ASan/TSan 对比:

┌──────────────────────────────────────────────────────────────────────┐
│ Sanitizer 全景对比:                                                 │
│                                                                      │
│ ┌───────────────────┬─────────────────────┬───────────────┬───────┐ │
│ │ 特性              │ ASan                 │ TSan          │ UBSan │ │
│ ├───────────────────┼─────────────────────┼───────────────┼───────┤ │
│ │ 检测类型          │ 内存错误             │ 线程错误       │ UB    │ │
│ │ 检测内容          │ 越界/使用后释放等     │ 数据竞争       │ 未定义行为 │
│ │ 性能开销          │ 2x-8x              │ 10x-15x      │ 1x-3x │ │
│ │ 内存开销          │ 2x (shadow)        │ 2x-4x (track) │ 低    │ │
│ │ 编译期开销        │ 中                  │ 高            │ 低    │ │
│ │ 检测精度          │ 高(字节级)        │ 高(H-B关系) │ 中    │ │
│ │ 误报率            │ 极低                │ 低            │ 低    │ │
│ │ 检测时机          │ 运行时              │ 运行时         │ 运行时 │ │
│ │ Swift 支持        │ ✅                   │ ✅             │ ✅    │ │
│ │ Objective-C 支持  │ ✅                   │ ✅             │ ⚠️    │ │
│ │ C/C++ 支持        │ ✅                   │ ✅             │ ✅    │ │
│ │ 生产可用          │ ❌                   │ ❌            │ ⚠️    │ │
│ │ Xcode 集成        │ 一键启用            │ 一键启用       │ 可选   │ │
│ └───────────────────┴─────────────────────┴───────────────┴───────┘ │
│                                                                      │
│ UBSan(UndefinedBehaviorSanitizer):                              │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ UBSan 检测内容:                                               │   │
│ │ • 整数溢出(signed integer overflow)                          │   │
│ │ • 除以零                                                        │   │
│ │ • 数组索引越界                                                 │   │
│ │ • 未初始化变量使用                                             │   │
│ │ • 空指针解引用                                                 │   │
│ │ • 对齐错误                                                     │   │
│ │ • 类型双关(type punning)                                    │   │
│ │ • 函数参数超出范围                                             │   │
│ │ • 枚举值超出范围                                               │   │
│ │ • 未对齐指针访问                                               │   │
│ │ • 无效的内存访问(aligned/unaligned access)                   │   │
│ │ • 虚函数调用(虚表指针无效)                                   │   │
│ │ • 无符号整数溢出                                              │   │
│ │ • 有符号整数溢出                                              │   │
│ │ • 移位溢出                                                    │   │
│ │ • 无效类型转换                                                 │   │
│ │ • 未定义的行为(strict aliasing)                             │   │
│ │                                                              │   │
│ │ UBSan 使用方式:                                              │   │
│ │ Xcode → Build Settings → clang - UndefinedBehaviorSanitizer  │   │
│ │ ───> YES                                                      │   │
│ │                                                              │   │
│ │ UBSan 特点:                                                  │   │
│ │ • 开销最低(相比 ASan/TSan)                                   │   │
│ │ • 可检测编译期无法发现的运行时 UB                              │   │
│ │ • 某些 UB 在生产环境也可以启用                                 │   │
│ │ • 不能检测所有 UB(部分需要编译期分析)                        │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

19. 内存调试实战

19.1 内存调试全栈方法

内存调试完整方法论:

┌──────────────────────────────────────────────────────────────────────┐
│ 内存调试分层策略:                                                   │
│                                                                      │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ Layer 1: 静态分析(编译期)                                     │   │
│ │  • Xcode Analyzer(⌘ + Shift + B)                            │   │
│ │  • Swift Compiler Warnings                                     │   │
│ │  • 循环引用静态检查                                              │   │
│ │  • 未使用变量警告                                               │   │
│ │  • 未初始化变量警告                                             │   │
│ │                                                              │   │
│ │ Layer 2: 编译期插桩(构建期)                                   │   │
│ │  • Address Sanitizer(ASan)                                   │   │
│ │  • Thread Sanitizer(TSan)                                    │   │
│ │  • UBSan(UBSanitizer)                                        │   │
│ │  • 编译时内存管理检查                                           │   │
│ │                                                              │   │
│ │ Layer 3: 运行时调试(开发阶段)                                 │   │
│ │  • LLDB 变量检查                                               │   │
│ │  • 断点调试                                                    │   │
│ │  • 内存断点(Watchpoint)                                      │   │
│ │  • 表达式求值(修改变量/调用方法)                              │   │
│ │                                                              │   │
│ │ Layer 4: 性能分析(测试阶段)                                   │   │
│ │  • Allocations(内存分配追踪)                                 │   │
│ │  • Leaks(内存泄漏检测)                                       │   │
│ │  • Time Profiler(CPU 分析)                                  │   │
│ │  • Core Animation(渲染分析)                                  │   │
│ │                                                              │   │
│ │ Layer 5: 生产监控(发布后)                                    │   │
│ │  • Crashlytics(崩溃报告)                                     │   │
│ │  • Memory Profiling(远程内存分析)                            │   │
│ │  • ANR 监控(Not-Responding)                                  │   │
│ │  • 自定义内存指标                                               │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 内存调试完整流程:                                                   │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │  1. 发现内存问题                                                │   │
│ │     • 内存增长(Allocations 观察)                               │   │
│ │     • 内存泄漏(Leaks 检测)                                     │   │
│ │     • 野指针崩溃(Zombies/ASan)                                 │   │
│ │     • 卡顿(Time Profiler)                                     │   │
│ │                                                              │   │
│ │  2. 定位问题                                                     │   │
│ │     • Allocations Snapshot 对比                                  │   │
│ │     • Leaks 调用栈分析                                           │   │
│ │     • ASan/TSan 崩溃报告                                         │   │
│ │     • LLDB 变量检查                                              │   │
│ │                                                              │   │
│ │  3. 修复问题                                                    │   │
│ │     • 打破循环引用                                              │   │
│ │     • 正确释放资源                                              │   │
│ │     • 添加边界检查                                              │   │
│ │     • 优化分配模式                                              │   │
│ │                                                              │   │
│ │  4. 验证修复                                                    │   │
│ │     • 重新 Profile 对比                                          │   │
│ │     • ASan/TSan 验证                                             │   │
│ │     • 回归测试                                                  │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

19.2 实战案例

内存调试实战案例:

┌──────────────────────────────────────────────────────────────────────┐
│ 案例 1:列表滚动内存泄漏                                               │
│                                                                      │
│ 问题描述:滑动列表时内存持续增长                                     │
│                                                                      │
│ 排查步骤:                                                           │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 1. Allocations → Record                                        │   │
│ │ 2. Snapshot A → 滑动 50 次                                      │   │
│ │ 3. Snapshot B → 滑动 100 次                                     │   │
│ │ 4. 对比 A→B → [MyCell] 增长 500KB                              │   │
│ │ 5. 双击 [MyCell] → 查看调用栈                                   │   │
│ │ 6. 发现 cellForRowAt 中创建的新对象未释放                       │   │
│ │ 7. 检查闭包捕获 self → weak self 修复                          │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 代码修复:                                                           │
│ // ❌ 泄漏:cellForRowAt 中创建闭包捕获 self                       │   │
│ func tableView(_ tableView: UITableView,                         │   │
│                cellForRowAt indexPath: IndexPath) -> UITableViewCell │   │
│     let cell = tableView.dequeueReusableCell(...)                  │   │
│     cell.titleLabel.text = item.title                               │   │
│     cell.onTap = { [self] in  // 💥 循环引用                       │   │
│         self.handleTap(item)                                       │   │
│     }                                                              │   │
│     return cell                                                    │   │
│                                                                    │   │
│ // ✅ 修复:weak self                                             │   │
│ cell.onTap = { [weak self] in  // ✅                              │   │
│     self?.handleTap(item)                                          │   │
│ }                                                                  │   │
│ └────────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────────┘

19.3 实战案例(续)

内存调试实战案例(续):

┌──────────────────────────────────────────────────────────────────────┐
│ 案例 2:页面切换内存泄漏                                             │
│                                                                      │
│ 问题描述:在两个 VC 间切换,内存持续增长                             │
│                                                                      │
│ 排查步骤:                                                           │
│ ┌────────────────────────────────────────────────────────────────┐   │
│ │ 1. Allocations → Record                                        │   │
│ │ 2. 对比切换前后的内存快照                                         │   │
│ │ 3. 发现 [MyViewController] 实例数持续增长                        │   │
│ │ 4. Leaks → 确认泄漏                                              │   │
│ │ 5. Leaks → 双击泄漏 → 查看调用栈                                │   │
│ │ 6. 发现 NavigationController 的 viewControllers 数组持有引用    │   │
│ │ 7. 发现闭包捕获 self → 循环引用                                 │   │
│ └────────────────────────────────────────────────────────────────┘   │
│                                                                      │
│ 代码修复:                                                           │   │
│ // ❌ 泄漏:闭包中 self 被 Timer 和 notification 同时捕获           │   │
│ class MyViewController: UIViewController {                            │   │
│     var timer: Timer?                                                  │   │
│     override func viewDidLoad() {                                     │   │
│         super.viewDidLoad()                                            │   │
│         timer = Timer.scheduledTimer(                                  │   │
│             withTimeInterval: 1.0,                                    │   │
│             repeats: true,                                            │   │
│             target: self,  // 💥 Timer 强引用 self                   │   │
│             selector: #selector(update),                              │   │
│             userInfo: nil,                                            │   │
│             repeats: true                                             │   │
│         )                                                             │   │
│         NotificationCenter.default.addObserver(                      │   │
│             self,  // 💥 通知强引用 self                              │   │
│             selector: #selector(didReceive),                          │   │
│             name: .MyEvent,                                           │   │
│             object: nil                                               │   │
│         )                                                             │   │
│     }                                                                 │   │
│     deinit {                                                         │   │
│         timer?.invalidate()                                          │   │
│         NotificationCenter.default.removeObserver(self)              │   │
│     }                                                                 │   │
│ }                                                                    │   │
│                                                                      │
│ // ✅ 修复:weak self + 正确的清理                                    │   │
│ override func viewDidLoad() {                                        │   │
│     super.viewDidLoad()                                               │   │
│     timer = Timer.scheduledTimer(                                   │   │
│         withTimeInterval: 1.0,                                      │   │
│         repeats: true) { [weak self] _ in                           │   │
│         self?.update()                                                │   │
│     }                                                                 │   │
│     notificationObserver = NotificationCenter.default                │   │
│         .addObserver(forName: .MyEvent,                             │   │
│                        object: nil,                                  │   │
│                        queue: .main) { [weak self] _ in             │   │
│             self?.didReceive()                                       │   │
│         }                                                            │   │
│ }                                                                    │   │
│ deinit {                                                             │   │
│     if let observer = notificationObserver {                        │   │
│         NotificationCenter.default.removeObserver(observer)         │   │
│     }                                                               │   │
│ }                                                                    │   │
└──────────────────────────────────────────────────────────────────────┘

19.4 内存调试工具对比

内存调试工具对比表:

┌──────────────────┬───────────────┬───────────────┬───────────────┬───────────────┐
│ 工具              │ 检测精度       │ 性能开销       │ 检测内容       │ 适用阶段      │
├──────────────────┼───────────────┼───────────────┼───────────────┼───────────────┤
│ Allocations      │ 高             │ 中            │ 内存分配/释放  │ 开发/测试     │
│ Leaks            │ 中高           │ 低            │ 内存泄漏       │ 开发/测试     │
│ Zombies          │ 高             │ 高            │ 野指针         │ 测试阶段      │
│ ASan             │ 极高(字节级) │ 高(2x-8x)    │ 内存错误       │ 测试阶段      │
│ TSan             │ 高             │ 高(10x-15x) │ 数据竞争       │ 测试阶段      │
│ UBSan            │ 中             │ 低(1x-3x)    │ UB             │ 开发/测试     │
│ Xcode Memory     │ 中高           │ 低            │ 内存布局可视化 │ 调试阶段      │
│ Graph Debugger   │ 中             │ 中            │ 对象图/引用    │ 调试阶段      │
│ LeakCanary       │ 高             │ 低            │ Android 泄漏   │ Android      │
│ 自定义 retain    │ 中             │ 低            │ 引用计数追踪    │ 开发阶段      │
│ Instruments VM   │ 中高           │ 低            │ 虚拟内存        │ 测试阶段      │
│ Memory Graph     │ 中             │ 低            │ 对象引用关系    │ 调试阶段      │
└──────────────────┴───────────────┴───────────────┴───────────────┴───────────────┘

20. 调试与 Android/Kotlin 对比

20.1 调试工具链对比

iOS 与 Android/Kotlin 调试工具链对比:

┌──────────────────────────────┬───────────────────────┬───────────────────────┐
│ 维度                        │ iOS                   │ Android/Kotlin        │
├──────────────────────────────┼───────────────────────┼───────────────────────┤
│ 集成调试器                   │ LLDB                  │ LLDB (NDK) / GDB     │
│ IDE 调试入口                 │ Xcode Debug Navigator │ Android Studio Debugger│
│ 断点管理                     │ Breakpoint Navigator  │ Breakpoint Dialog      │
│ 条件断点                     │ ✅ 表达式条件          │ ✅ 表达式条件           │
│ 日志断点                     │ ✅ breakpoint command  │ ✅ Logcat Filter      │
│ 异常断点                     │ ✅ Exception BP       │ ✅ Exception BP        │
│ 观察断点 (Watchpoint)        │ ✅ HW debug regs      │ ❌ (需源码修改)       │
│ 内存分析工具                 │ Allocations + Leaks   │ Android Studio Memory  │
│ CPU 分析工具                 │ Time Profiler         │ CPU Profiler           │
│ 渲染分析工具                 │ Core Animation        │ Layout Inspector       │
│ 网络分析工具                 │ Network               │ Network Profiler       │
│ GPU 分析工具                 │ Metal Shader          │ GPU Profiler           │
│ 线程分析工具                 │ Thread Profiler       │ Thread Profiler        │
│ 崩溃分析                     │ symbolicatecrash +    │ asecrash/symbolicate   │
│                              │ dSYM                  │                      │
│ 内存泄漏检测                 │ Allocations/Leaks     │ LeakCanary            │
│ 地址安全检测 (ASan)          │ ✅ Xcode Scheme       │ ✅ ndk-build CMake     │
│ 线程安全检测 (TSan)          │ ✅ Xcode Scheme       │ ✅ ndk-build CMake     │
│ 未定义行为检测 (UBSan)       │ ✅ Xcode Scheme       │ ✅ ndk-build CMake     │
│ 设备日志                     │ Console               │ Logcat                 │
│ 模拟器                       │ Simulator             │ Android Emulator       │
│ 网络模拟                     │ Network Link Cond.    │ Network Link Cond.     │
│ 性能 profiling               │ Instruments           │ Android Studio Profiler│
│ 热修复                       │ ❌ (无官方支持)       │ Hotfix (ClassLink)    │
│ 远程调试                     │ Xcode Remote Debug    │ adb forward / Chrome   │
│ 崩溃上报                     │ Crashlytics           │ Firebase Crashlytics   │
│ 内存图                       │ Memory Graph Debugger │ Object Inspector       │
└──────────────────────────────┴───────────────────────┴───────────────────────┘

20.2 LLDB vs GDB/LLDB (Android) 对比

LLDB 在 iOS 与 Android 中的对比:

┌──────────────────────────────┬───────────────────────┬───────────────────────┐
│ 特性                        │ iOS (LLDB)            │ Android (LLDB)        │
├──────────────────────────────┼───────────────────────┼───────────────────────┤
│ 默认调试器                   │ LLDB                  │ LLDB (NDK) / GDB     │
│ 进程控制机制                 │ ptrace + Mach Exception│ ptrace + siginfo      │
│ 架构支持                     │ ARM64 / x86_64       │ ARM / ARM64 / x86     │
│ 动态库加载钩子               │ dyld helper           │ linker hook (Android)  │
│ 符号化方式                   │ DWARF + dSYM          │ DWARF + .so symbols   │
│ Swift 支持                   │ ✅ 完整支持            │ ❌ 无 (仅 C/C++)      │
│ Objective-C 支持             │ ✅ 完整支持            │ ⚠️ 有限支持           │
│ JNI 支持                     │ ❌                     │ ✅ (NDK)              │
│ C/C++ 支持                   │ ✅                    │ ✅ (NDK)              │
│ 内存分析                     │ Allocations/Leaks     │ Memory Profiler        │
│ 崩溃分析                     │ symbolicatecrash      │ asecrash               │
│ Sanitizer 支持               │ ASan/TSan/UBSan       │ ASan/TSan/UBSan       │
│ 性能分析                     │ Instruments           │ perfetto/Android Profiler│
│ 远程调试                     │ Xcode Remote          │ adb forward + GDB     │
│ GUI 集成                     │ Xcode Debug Navigator │ Android Studio Debugger│
└──────────────────────────────┴───────────────────────┴───────────────────────┘

20.3 Instruments vs Android Profiler 对比

Instruments vs Android Profiler 对比:

┌──────────────────┬───────────────────────┬───────────────────────┐
│ 功能             │ iOS Instruments        │ Android Profiler       │
├──────────────────┼───────────────────────┼───────────────────────┤
│ CPU 分析         │ Time Profiler         │ CPU Profiler           │
│ 原理             │ 采样 (sampling)        │ 采样 (sampling)        │
│ 火焰图           │ ✅                    │ ✅                     │
│ 函数耗时         │ ✅                    │ ✅                     │
│ 调用链分析       │ ✅                    │ ✅                     │
│ 主线程监控       │ ✅                    │ ✅                     │
│ 异步任务分析     │ ✅                    │ ✅                     │
│                  │                       │                       │
│ 内存分析         │ Allocations + Leaks   │ Memory Profiler        │
│ 内存分配追踪     │ ✅                    │ ✅                     │
│ 内存泄漏检测     │ ✅                    │ ✅ (LeakCanary)        │
│ 对象图           │ ✅ (Graph Debugger)   │ ✅ (Object Inspector)  │
│ GC 分析          │ ❌ (ARC)             │ ✅ (Garbage Collection)│
│ 内存峰谷         │ ✅                    │ ✅                     │
│                  │                       │                       │
│ 渲染分析         │ Core Animation        │ Layout Inspector        │
│ GPU 分析         │ Metal Shader          │ GPU Profiler           │
│ 离屏渲染检测     │ ✅                    │ ⚠️ 间接支持            │
│ 帧率监控         │ ✅                    │ ✅                     │
│                  │                       │                       │
│ 网络分析         │ Network               │ Network Profiler        │
│ HTTP 请求追踪    │ ✅                    │ ✅                     │
│ WebSocket 追踪   │ ✅                    | ✅                     │
│ 延迟分析         │ ✅                    │ ✅                     │
│                  │                       │                       │
│ 能耗分析         │ Energy Log            │ Battery Profiler        │
│ CPU 能耗         │ ✅                    │ ✅                     │
│ 网络能耗         │ ✅                    │ ✅                     │
│ 屏幕能耗         │ ✅                    │ ✅                     │
│                  │                       │                       │
│ 系统追踪         │ System Trace          │ Perfetto                │
│ 内核事件         │ ✅                    │ ✅                     │
│ 进程调度         │ ✅                    │ ✅                     │
│ I/O 追踪         │ ✅                    │ ✅                     │
│ 帧渲染           │ ✅                    │ ✅                     │
└──────────────────┴───────────────────────┴───────────────────────┘

20.4 崩溃日志分析对比

崩溃日志分析:iOS vs Android

┌──────────────────────────────┬───────────────────────┬───────────────────────┐
│ 维度                        │ iOS                   │ Android               │
├──────────────────────────────┼───────────────────────┼───────────────────────┤
│ 崩溃文件格式                 │ .crash (UUID 匹配)    │ .txt / .log           │
│ 符号文件                     │ dSYM (DWARF)         │ .so symbols           │
│ 符号化工具                   │ symbolicatecrash      | asecrash/symbolicate  │
│ dSYM 管理                    │ Xcode Archive 自动保存  │ 需手动保存             │
│ UUID 匹配                    │ ✅                    │ ✅                    │
│ Native 崩溃                  │ ✅ (Mach Exception)   │ ✅ (Signal)           │
│ Java/Kotlin 崩溃             │ ❌                     | ✅ (Throwable)        │
│ Objective-C 异常             │ ✅ (NSException)      | ❌                     |
│ JNI 崩溃                     | ⚠️ 部分支持           │ ✅                    │
│ 调用栈格式                   │ 符号+offset           │ 符号+offset           │
│ 寄存器信息                   | ✅                    │ ✅                    │
│ VM 区域信息                  │ ✅                    │ ✅                    │
│ 崩溃原因分类                 │ EXC_BAD_ACCESS 等     │ SIGABRT/SIGSEGV 等    │
│ 自动收集                     │ Crashlytics           │ Firebase Crashlytics  │
│ 远程符号化                   | ✅ (Firebase)         │ ✅ (Firebase)          │
└──────────────────────────────┴───────────────────────┴───────────────────────┘

20.5 Logcat vs Console 对比

日志系统:Logcat (Android) vs Console (iOS)

┌──────────────────────────────┬───────────────────────┬───────────────────────┐
│ 维度                        │ iOS Console           │ Android Logcat        │
├──────────────────────────────┼───────────────────────┼───────────────────────┤
│ 日志来源                     | 系统 + 应用           │ 系统 + 应用           │
│ 查看方式                     | Xcode Console         │ Android Studio Logcat │
│ 实时输出                     | ✅                    │ ✅                    │
│ 历史日志                     | ✅ (保存 .txt)        │ ✅ (保存 .txt)        │
│ 过滤                       | ✅ (搜索/标签)        │ ✅ (Tag/Level/PID)    │
│ 崩溃日志                     | ✅ (自动捕获)         │ ✅ (自动捕获)         │
│ 自定义日志级别               | NSLog/OSLog           │ Log.d/w/e/i/v         │
│ 结构化日志                   | OSLog (OSLogSource)   │ SLF4J/Kotlin Logging  │
│ 异步日志                     | ✅                    │ ✅                    │
│ 性能分析                     | Instruments           │ Android Profiler       │
│ 设备日志导出                 | Console.app           | logcat > file.txt     │
│ 远程日志                     | Xcode Remote          | adb logcat -d          │
│ 日志持久化                   | Console.app 自动保存   | logcat 配置文件        │
└──────────────────────────────┴───────────────────────┴───────────────────────┘

21. 面试考点汇总

21.1 高频面试题

基础题

1. LLDB 常用调试命令?
   答:
   • po/p:打印对象/值
   • breakpoint set/clear/delete:断点管理
   • n/s/c:执行控制(next/step/continue)
   • fr var:查看帧变量
   • watchpoint:内存断点
   • bt/backtrace:堆栈回溯
   • memory read/x:内存查看
   • expr/e:表达式求值

2. Instruments 主要工具?
   答:
   • Time Profiler:CPU 时间分析(采样原理)
   • Allocations:内存分配追踪(Snapshot 机制)
   • Leaks:内存泄漏检测(标记-清除算法)
   • Zombies:悬垂指针检测(对象替换机制)
   • Core Animation:动画性能(离屏渲染检测)
   • System Trace:系统级追踪

3. 内存泄漏常见原因?
   答:
   • 闭包循环引用([weak self]/[unowned self])
   • NSTimer/KVO/NotificationCenter 未清理
   • CADisplayLink 未 invalidate
   • Delegate 未置 nil
   • 缓存未限制大小
   • 异步任务持有 self 引用

4. ASan 和 TSan 的区别?
   答:
   • ASan:检测内存错误(越界、使用后释放等),通过 shadow memory
   • TSan:检测数据竞争(多线程同时访问),通过 Happens-Before
   • ASan 开销 2x-8x,TSan 开销 10x-15x
   • 两者都可在 Xcode 中一键启用

5. 如何分析崩溃日志?
   答:
   • 通过 dSYM 文件符号化(UUID 匹配)
   • symbolicatecrash 命令行工具
   • 关注崩溃类型和调用栈
   • 常见崩溃:EXC_BAD_ACCESS、SIGABRT、EXC_CRASH

进阶题

6. LLDB 断点的底层实现原理?
   答:
   • x86_64:第一条指令替换为 0xCC (INT3)
   • ARM64:第一条指令替换为 0xD4200000 (BRK #0x1)
   • 触发 SIGTRAP → 内核通过 ptrace 通知 LLDB
   • LLDB 暂停进程,显示上下文
   • 用户点击 continue → LLDB 恢复原始指令

7. Allocations 中 Snapshot 的作用?
   答:
   • 创建内存快照(Snapshot A → Snapshot B)
   • 对比两次快照的内存差异(Byte Increase)
   • 定位内存增长源头
   • 识别循环引用(Retain Cycle 检测)

8. Zombies 工具的工作原理?
   答:
   • 拦截 -release,不 dealloc,改为"僵尸对象"
   • 设置 isa 指向 _NSZombie_<ClassName>
   • 当僵尸对象收到消息时,打印崩溃信息
   • 输出:Message sent to deallocated instance

9. Time Profiler 的采样原理?
   答:
   • 每隔 1ms(1000Hz)发送 SIGPROF 信号
   • 内核暂停进程,保存当前寄存器状态
   • 通过 symbolication 将地址映射到函数名
   • 将调用栈入栈到采样树
   • 输出火焰图(Flame Graph)

10. Core Animation 离屏渲染的检测方法?
    答:
    • Instruments → Core Animation → Offscreen Draws
    • 常见原因:圆角、阴影、clip、mask
    • 修复:使用 CAShapeLayer + bezierPath
    • 避免:masksToBounds、复杂圆角

21.2 面试回答模板

> "iOS 调试主要用 Xcode 内置的 LLDB 和 Instruments。
> LLDB 负责断点调试和变量检查,支持条件断点、日志断点、观察断点等。
> Instruments 做性能分析(Time Profiler/Allocations/Leaks/Core Animation)。
> 内存泄漏用 Allocations + Leaks 联合检测,数据竞争用 TSan,内存错误用 ASan。
> 崩溃日志通过 dSYM 文件符号化分析(symbolicatecrash)。
> 对于模拟器调试,Xcode Simulator 提供丰富的模拟功能(弱网/GPS/电量等)。
> 生产环境监控主要依赖 Crashlytics 等第三方工具。"

> "LLDB 和 Instruments 是 iOS 调试的两大核心工具。
> LLDB 是命令行调试器,通过 ptrace + Mach Exception 实现进程控制。
> 断点本质是修改代码的第一条指令为断点指令(x86: INT3 / ARM64: BRK)。
> Instruments 是性能分析工具集,通过 hooks + 采样实现无侵入分析。
> Allocations 通过 hook malloc/free 实现内存分配追踪。
> Leaks 通过标记-清除算法检测内存泄漏。
> Time Profiler 通过采样(SIGPROF 信号)实现 CPU 分析。
> ASan 通过 shadow memory 实现内存错误检测。
> TSan 通过 Happens-Before 关系实现数据竞争检测。"

> "iOS 和 Android 调试工具各有特点:
> iOS:Xcode + LLDB + Instruments 一体化
> Android:Android Studio + Logcat + Profiler + LeakCanary 组合
> iOS 的 dSYM 符号化是崩溃分析的核心
> Android 的 Logcat 是日志分析的核心
> iOS 的 Instruments 功能比 Android Profiler 更丰富
> Android 的 LeakCanary 比 iOS 的 Leaks 更自动化
> 两者都支持 ASan/TSan 检测内存/线程错误"

21.3 面试考点矩阵

iOS 调试面试考点矩阵:

┌──────────────┬──────────┬──────────┬──────────┬──────────┬──────────┐
│ 知识点        │ 初级     │ 中级      │ 高级      │ 专家级    │ 面试频率 │
├──────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
│ LLDB 基本命令 │ ✅       │ ✅       │ ✅       │ ✅       │ ⭐⭐⭐⭐⭐ │
│ 断点类型      │ ✅       │ ✅       │ ✅       │ ✅       │ ⭐⭐⭐⭐⭐ │
│ Instruments   │ ✅       │ ✅       │ ✅       │ ✅       │ ⭐⭐⭐⭐  │
│ Allocations   │ ✅       │ ✅       | ✅       │ ✅       │ ⭐⭐⭐⭐  │
│ Leaks         │ ✅       | ✅       │ ✅       │ ✅       │ ⭐⭐⭐⭐⭐ │
│ Time Profiler │ ❌       │ ✅       │ ✅       │ ✅       │ ⭐⭐⭐⭐  │
│ Zombies       │ ❌       │ ✅       │ ✅       │ ✅       │ ⭐⭐⭐   │
│ ASan/TSan     | ❌       │ ✅       │ ✅       │ ✅       │ ⭐⭐⭐⭐  │
│ dSYM 符号化   │ ❌       │ ✅       │ ✅       │ ✅       │ ⭐⭐⭐⭐  │
│ Core Anim.    │ ❌       │ ✅       │ ✅       │ ✅       │ ⭐⭐⭐   │
│ System Trace  │ ❌       │ ❌       │ ✅       │ ✅       │ ⭐⭐    │
│ LLDB 脚本     │ ❌       │ ❌       │ ✅       │ ✅       │ ⭐⭐    │
│ Sanitizer 原理 │ ❌       │ ❌       │ ✅       │ ✅       │ ⭐⭐⭐   │
│ 崩溃分析      │ ❌       │ ✅       │ ✅       │ ✅       │ ⭐⭐⭐⭐  │
│ iOS vs Android │ ❌       │ ❌       | ✅       │ ✅       │ ⭐⭐⭐   │
└──────────────┴──────────┴──────────┴──────────┴──────────┴──────────┘

面试准备建议:
• 初级:掌握 LLDB 基本命令 + 断点使用
• 中级:熟练使用 Instruments + Leaks + Allocations
• 高级:理解 ASan/TSan 原理 + 崩溃符号化
• 专家:LLDB 脚本扩展 + System Trace + 底层原理

附录

A. LLDB 命令速查表

LLDB 命令速查:

┌──────┬───────────────────────┬──────────────────────────────┐
│ 类别  │ 命令                  │ 说明                          │
├──────┼───────────────────────┼──────────────────────────────┤
│ 断点  │ breakpoint list       │ 列出所有断点                  │
│      │ breakpoint delete N   │ 删除断点 N                    │
│      │ breakpoint set -n fn  │ 按函数名设置断点              │
│      │ breakpoint set -f f -l l │ 按文件+行号设置断点       │
│      │ breakpoint enable N   │ 启用断点 N                    │
│      │ breakpoint disable N  │ 禁用断点 N                    │
│      │ breakpoint ignore N c │ 断点 N 忽略 c 次             │
│      │ breakpoint command add │ 添加断点命令                  │
│      │                       │ N                             │
│ 执行  │ continue              │ 继续执行                      │
│      │ step                  │ 单步进入函数                  │
│      │ next                  │ 单步跳过函数                  │
│      │ finish                │ 执行到当前函数返回            │
│      │ jump to line N        │ 跳转到行 N                    │
│      │ thread return expr    │ 直接返回(修改变量)          │
│ 变量  │ po expr               │ 打印对象                      │
│      │ p expr                │ 打印值                        │
│      │ expr -- expr          │ 求表达式                      │
│      │ frame variable        │ 查看帧变量                    │
│      │ register read         │ 查看寄存器                    │
│ 内存  │ memory read addr      │ 读取内存                      │
│      │ memory write addr val │ 写入内存                      │
│      │ memscan addr sz val   │ 内存扫描                      │
│      │ heap dump             │ 堆转储                        │
│      │ heap query Type       │ 堆查询                        │
│ 线程  │ thread list           │ 列出线程                      │
│      │ thread select N       │ 选择线程 N                    │
│      │ thread backtrace      │ 线程 backtrace                │
│      │ thread backtrace all  │ 所有线程 backtrace            │
│ 模块  │ image list            │ 列出镜像                      │
│      │ image lookup -a addr  │ 查找地址                      │
│      │ module list           │ 列出模块                      │
│ 汇编  │ disassemble           │ 反汇编                        │
│      │ disassemble -n fn     │ 反汇编函数                    │
│ 脚本  │ command alias a b     │ 命令别名                      │
│      │ script import file.py │ 导入 Python 脚本              │
│      │ settings set x y      │ 设置选项                      │
│ 观察  │ watchpoint set var    │ 设置观察点                    │
│      │ watchpoint list       │ 列出观察点                    │
│      │ watchpoint delete N   │ 删除观察点 N                  │
└──────┴───────────────────────┴──────────────────────────────┘

B. Instruments 工具速查表

Instruments 工具速查:

┌───────────────────┬──────────────────────────────┐
│ 工具              │ 用途                         │
├───────────────────┼──────────────────────────────┤
│ Time Profiler     │ CPU 性能分析(采样)         │
│ Allocations       │ 内存分配追踪                 │
│ Leaks             │ 内存泄漏检测                 │
│ Zombies           │ 悬垂指针检测                 │
│ Core Animation    │ 渲染性能分析                 │
│ Network           │ 网络请求分析                 │
│ Energy Log        │ 能耗分析                     │
│ System Trace      │ 系统级追踪                   │
│ File Activity     │ 文件操作分析                 │
│ OpenGL ES         │ GPU 渲染分析                 │
│ Metal Shader      │ Metal 着色器分析             │
│ Thread Activator  │ 线程创建/销毁                │
│ Activity Monitor  │ 进程活动监控                 │
│ VM Tracker        │ 虚拟内存追踪                 │
│ ObjectAlloc       │ Objective-C 对象追踪         │
│ API Log           │ API 调用日志                 │
│ GPU Debugger      │ GPU 调试                     │
│ Metal System Trace│ Metal 系统追踪               │
│ Disk Activity     │ 磁盘活动分析                 │
│ Network Link Cond │ 网络链接条件器               │
│ Time Profiler +   │ CPU+GPU 联合分析             │
│ GPU Profiler      │                           │
└───────────────────┴──────────────────────────────┘

C. 常见崩溃码速查表

崩溃码速查:

┌──────────────────────┬──────────────────────────────┐
│ 崩溃码               │ 含义                          │
├──────────────────────┼──────────────────────────────┤
│ EXC_BAD_ACCESS       │ 内存访问错误(野指针)        │
│ EXC_CRASH            │ 进程崩溃                      │
│ EXC_ARITHMETIC       │ 算术错误(除零/溢出)         │
│ EXC_BREAKPOINT       │ 断点/断言失败                 │
│ SIGABRT              │ 进程中止(异常未捕获)        │
│ SIGSEGV              │ 段错误(非法内存访问)         │
│ SIGBUS               │ 总线错误(对齐错误)           │
│ SIGILL               │ 非法指令                      │
│ SIGFPE               │ 浮点异常                      │
│ SIGPIPE              │ 管道破裂                      │
│ SIGKILL              │ 强制终止(内存不足/超时)      │
│ MACH_SEND_INVALID    │ Mach 消息发送错误             │
│ KERN_PROTECTION      │ 内存保护失败                  │
│ KERN_INVALID_ADDRESS │ 无效地址                      │
│ EXC_ARM_DA_ALIGN     │ ARM 对齐异常                  │
└──────────────────────┴──────────────────────────────┘

D. Xcode 调试快捷键速查

Xcode 调试快捷键:

┌───────────────────────────┬──────────────────────────────┐
│ 快捷键                    │ 功能                          │
├───────────────────────────┼──────────────────────────────┤
│ ⌘ + R                    │ 运行/调试                    │
│ ⌘ + I                    │ Profile (Instruments)         │
│ ⌘ + Shift + L            │ 导航列表                     │
│ ⌘ + Shift + C            │ 控制台                        │
│ ⌘ + 5                    │ Debug Navigator               │
│ ⌘ + 6                    │ Variables (变量观察器)        │
│ ⌘ + 7                    │ Memory (内存视图)             │
│ ⌘ + 8                    │ Threads (线程面板)            │
│ ⌘ + 9                    │ Console (控制台)              │
│ ⌘ + Shift + 2            │ Devices and Simulators        │
│ F5                       │ Step Over                    │
│ F6                       │ Step Into                    │
│ F7                       │ Step Over (Skip Function)     │
│ F8                       │ Step Out                     │
│ ⌘ + Y                    │ 条件断点                     │
│ ⌘ + ⌥ + Y              │ 日志断点                     │
│ ⌘ + ⌥ + Enter          │ 折叠/展开代码                │
│ ⌘ + ⌥ + ↑/↓            │ 移动行                       │
│ ⌘ + Click                │ 跳转到定义                    │
│ ⌘ + ⇧ + Click            │ 跳转到声明                    │
│ ⌘ + [ / ⌘ + ]          │ 折叠/展开                    │
│ ⌘ + Option + [ / ]      │ 展开/折叠                    │
└───────────────────────────┴──────────────────────────────┘

本文档对标 Android 26_Xcode_Debug 的深度,涵盖 iOS 调试全栈知识体系