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);
}
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
# 断点操作
比如,你想在 main()
函数入口打个断点:
(lldb) break set -n main
当然我也可以在设定在具体某一行打断点,例如,我们想在第 13 行打上断点,可以执行
(lldb) break set -f a.cpp -l 13
Breakpoint 2: where = a`main + 52 at a.cpp:13:17, address = 0x0000000100003f14
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
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.
2
3
4
5
6
7
8
9
10
11
12
13
使用 run
启动程序的时候,执行到断点会自动停下来
# 单步到下一行
next
不进函数,直接跳转到下一步
(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.
2
3
4
5
6
7
8
9
10
11
12
# 继续执行到下一个断点
continue
# 查看变量的值
frame variable
查看当前函数作用域里面的变量
(lldb) frame variable
(int) p = 0
(int) x = 63471776
(int) i = 1
2
3
4
如果只想知道一个变量的值,可以使用 frame variable [变量名]
(lldb) frame variable i
(int) i = 1
2
使用 print [变量名]
可以打印变量的值,也可以简写成 p
(lldb) print i
(int) 1
2
甚至可以打印函数的调用结果
(lldb) print F(3)
(int) 6
2
你还可以开启 表达式观察,程序一走到断点就自动显示变化
(lldb) watchpoint set variable [变量名]
每次 continue
后,当指定为 watchpoint 观察的变量修改后会自动停下
当然还可以给观察点加条件,例如:当 的时候停下
watchpoint modify -c "p == 5"
使用 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
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
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 a
F(n=5) at a.cpp:6:6` 这是 当前栈帧(栈的顶部)。- 你现在正停在
F
函数的第 6 行:if (n == 0) return 1;
。 n=5
是传递给F
函数的参数,表示你在计算F(5)
。
- 你现在正停在
frame #1: 0x0000000100003f60 a
main at a.cpp:17:10这是上一个栈帧,也就是调用
F(5)` 的地方。main
函数在a.cpp
的第 17 行停下:int x = F(5);
。- 这是函数
F
的调用位置。
frame #2: 0x0000
这是栈的 最底层,指向main
函数的返回地址或程序的结束。
Gitalking ...