Martian148's blog Martian148's blog
首页
  • ICPC 算法笔记
  • ICPC 算法题解
  • 体系结构
  • 高等数学
  • 线性代数
  • 概率论与数理统计
  • 具体数学
  • Martian148的奇思妙想
  • 游记
  • 通识课笔记
关于
  • useful 网站
  • 友情链接
  • 分类
  • 归档

Martian148

一只热爱文科的理科生
首页
  • ICPC 算法笔记
  • ICPC 算法题解
  • 体系结构
  • 高等数学
  • 线性代数
  • 概率论与数理统计
  • 具体数学
  • Martian148的奇思妙想
  • 游记
  • 通识课笔记
关于
  • useful 网站
  • 友情链接
  • 分类
  • 归档
  • ACM - ICPC

  • 编程语言

    • C++

      • lldb 调试
        • 安装
        • 基本操作
          • 启动 lldb
          • 断点操作
          • 运行程序
          • 单步到下一行
          • 继续执行到下一个断点
          • 查看变量的值
          • 进入函数
        • 进阶操作
          • 当前线程的调用栈
    • Java

  • 体系结构

  • Web

  • 人工智能

  • 计算机网络

  • 数据库

  • 编程工具

  • 计算机科学
  • 编程语言
  • C++
martian148
2025-04-10
目录

lldb 调试

# lldb 断点调试

# 安装

Mac 操作系统使用 lldb 即可,和 gdb 等价

# 基本操作

假设这个是我们的程序 a.cpp

#include <cstdio>
#include <iostream>
using namespace std;

int F(int n) {
	if (n == 0) return 1;
	return n * F(n - 1);
}

int main() {
	int p = 0;
	for (int i = 1; i <= 10; i++) {
		printf("%d ", i * i);
		p += 1;
	}

	int x = F(5);
	printf("\n%d\n", x);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

我们使用命令行编译 g++ a.cpp -o a -g,-g 表示编译时带有参数信息

# 启动 lldb

lldb a
1

# 断点操作

比如,你想在 main() 函数入口打个断点:

(lldb) break set -n main
1

当然我也可以在设定在具体某一行打断点,例如,我们想在第 13 行打上断点,可以执行

(lldb) break set -f a.cpp -l 13
Breakpoint 2: where = a`main + 52 at a.cpp:13:17, address = 0x0000000100003f14
1
2

查看断点列表

(lldb) break list
Current breakpoints:
1: name = 'main', locations = 1
  1.1: where = a`main + 16 at a.cpp:11:6, address = 0x0000000100003ef0, unresolved, hit count = 0 

2: file = 'a.cpp', line = 13, exact_match = 0, locations = 1
  2.1: where = a`main + 52 at a.cpp:13:17, address = 0x0000000100003f14, unresolved, hit count = 0 
1
2
3
4
5
6
7

删除断点

我们通过 break list 操作可以知道现在的所有断点

我们可以通过 breakpoint delete [编号] 来删除指定的断点

也可以通过 breakpoint delete 来删除所有断点

# 运行程序

(lldb) run
Process 13718 launched: '/Users/martian148/Desktop/test/a' (arm64)
Process 13718 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100003ef0 a`main at a.cpp:11:6
   8    }
   9   
   10   int main() {
-> 11           int p = 0;
   12           for (int i = 1; i <= 10; i++) {
   13                   printf("%d ", i * i);
   14                   p += 1;
Target 0: (a) stopped.
1
2
3
4
5
6
7
8
9
10
11
12
13

使用 run 启动程序的时候,执行到断点会自动停下来

# 单步到下一行

next
1

不进函数,直接跳转到下一步

(lldb) next
Process 13718 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
    frame #0: 0x0000000100003ef4 a`main at a.cpp:12:11
   9   
   10   int main() {
   11           int p = 0;
-> 12           for (int i = 1; i <= 10; i++) {
   13                   printf("%d ", i * i);
   14                   p += 1;
   15           }
Target 0: (a) stopped.
1
2
3
4
5
6
7
8
9
10
11
12

# 继续执行到下一个断点

continue
1

# 查看变量的值

frame variable
1

查看当前函数作用域里面的变量

(lldb) frame variable
(int) p = 0
(int) x = 63471776
(int) i = 1
1
2
3
4

如果只想知道一个变量的值,可以使用 frame variable [变量名]

(lldb) frame variable i
(int) i = 1
1
2

使用 print [变量名]可以打印变量的值,也可以简写成 p

(lldb) print i
(int) 1
1
2

甚至可以打印函数的调用结果

(lldb) print F(3)
(int) 6
1
2

你还可以开启 表达式观察,程序一走到断点就自动显示变化

(lldb) watchpoint set variable [变量名]
1

每次 continue 后,当指定为 watchpoint 观察的变量修改后会自动停下

当然还可以给观察点加条件,例如:当 p=5p=5p=5 的时候停下

watchpoint modify -c "p == 5"
1

使用 watchpoint list 可以查看观察点列表,使用 watchpoint delete [编号] 可以删除观察点

# 进入函数

当运行到第 17 行,使用 step 就可以进入到函数内部了,使用 next 会跳过函数

(lldb) break set -f a.cpp -l 17
Breakpoint 2: where = a`main + 120 at a.cpp:17:10, address = 0x0000000100003f58
(lldb) continue
Process 14799 resuming
Process 14799 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
    frame #0: 0x0000000100003f58 a`main at a.cpp:17:10
   14                   p += 1;
   15           }
   16  
-> 17           int x = F(5);
   18           printf("\n%d\n", x);
   19   }
Target 0: (a) stopped.
(lldb) step
Process 14799 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x0000000100003e8c a`F(n=5) at a.cpp:6:6
   3    using namespace std;
   4   
   5    int F(int n) {
-> 6            if (n == 0) return 1;
   7            return n * F(n - 1);
   8    }
   9   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

可以看到,进入了函数 F 中

# 进阶操作

# 当前线程的调用栈

当我们第一次进度 F 函数,即 F(5) 时,运行 bt 命令,就可以现实当前线程的调用栈了

(lldb) step
Process 14799 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x0000000100003e8c a`F(n=5) at a.cpp:6:6
   3    using namespace std;
   4   
   5    int F(int n) {
-> 6            if (n == 0) return 1;
   7            return n * F(n - 1);
   8    }
   9   
Target 0: (a) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = step in
  * frame #0: 0x0000000100003e8c a`F(n=5) at a.cpp:6:6
    frame #1: 0x0000000100003f60 a`main at a.cpp:17:10
    frame #2: 0x000000019a234274 dyld`start + 2840
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

下面逐行解释一下

  • thread #1, queue = 'com.apple.main-thread', stop reason = step in这表示当前是在 主线程 (main-thread) 中,程序因为你执行了 step 命令而停下来了。step in 意味着你进入了函数 F(n=5)。

  • frame #0: 0x0000000100003e8c aF(n=5) at a.cpp:6:6` 这是 当前栈帧(栈的顶部)。

    • 你现在正停在 F 函数的第 6 行:if (n == 0) return 1;。
    • n=5 是传递给 F 函数的参数,表示你在计算 F(5)。
  • frame #1: 0x0000000100003f60 amain at a.cpp:17:10这是上一个栈帧,也就是调用F(5)` 的地方。

    • main 函数在 a.cpp 的第 17 行停下:int x = F(5);。
    • 这是函数 F 的调用位置。
  • frame #2: 0x0000 这是栈的 最底层,指向 main 函数的返回地址或程序的结束。

ICPC 算法题解
开发环境配置

← ICPC 算法题解 开发环境配置→

最近更新
01
在 ACM 集训队年会上的讲话
07-01
02
计算机网络笔记
06-13
03
LLM101 NLP学习笔记
06-02
更多文章>
Theme by Vdoing | Copyright © 2024-2025 Martian148 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式