// mycmd.c
#include <stdio.h>
int Sum(int s, int e)
{
int result = 0;
for(int i = s; i <= e; i++)
{
result += i;
}
return result;
}
int main()
{
int start = 1;
int end = 100;
printf("I will begin\n");
int n = Sum(start, end);
printf("running done, result is: [%d-%d]=%d\n", start, end, n);
return 0;
}
• 程序的发布方式有两种, debug
模式和 release
模式, Linux gcc/g++
出来的二进制程序,默认是 release
模式。
• 要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g
选项,如果没有添加,程序无法被编译
$ gcc mycmd.c -o mycmd # 默认模式,不支持调试
$ file mycmd
mycmd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-x86-64.so.2,
BuildID[sha1]=82f5cbaada10a9987d9f325384861a88d278b160, for GNU/Linux
3.2.0, not stripped
$ gcc mycmd.c -o mycmd -g # debug模式
$ file mycmd
mycmd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-x86-64.so.2,
BuildID[sha1]=3d5a2317809ef86c7827e9199cfefa622e3c187f, for GNU/Linux
3.2.0, with debug_info, not stripped
gdb binFile
ctrl + d
或 quit
调试命令按下ESC键进入代码窗口,此时可以上下浏览代码,并且可以进行一系列的操作:
按键 | 操作 |
---|---|
空格键 | 设置或者取消断点; |
o | 查看代码所在的文件; |
/ 或者 ? | 在代码中搜索字符串; |
- | 缩小代码窗口; |
+ | 扩大代码窗口; |
gg | 光标移动到文件头部; |
GG | 光标移动到文件尾部; |
ctrl + b | 代码向上翻一页; |
ctrl + u | 代码向上翻半页; |
ctrl + f | 代码向下翻一页; |
ctrl + d | 代码向下翻半页; |
按下i键回到调试窗口,进入调试模式,使用的调试指令与GDB几乎一样!
命令 | 作用 | 样例 |
---|---|---|
list/l | 显⽰源代码,从上次位置开始,每次列出 | list/l 10 |
list/l 函数名 | 列出指定函数的源代码 | list/l main |
list/l ⽂件名:行号 | 列出指定⽂件的源代码 | list/l mycmd.c:1 |
r/run | 从程序开始连续执⾏ | run |
n/next | 单步执行,不进⼊函数内部 | next |
s/step | 单步执行,进⼊函数内部 | step |
break/b [⽂件名:]行号 | 在指定⾏号设置断点 | break 10 break test.c:10 |
break/b 函数名 | 在函数开头设置断点 | break main |
info break/b | 查看当前所有断点的信息 | info break |
finish | 执⾏到当前函数返回,然后停⽌ | finish |
print/p 表达式 | 打印表达式的值 | print start+end |
p 变量 | 打印指定变量的值 | p x |
set var 变量=值 | 修改变量的值 | set var i=10 |
continue/c | 从当前位置开始连续执⾏程序 | continue |
delete/d breakpoints | 删除所有断点 | delete breakpoints |
delete/d breakpoints n | 删除序号为n的断点 | delete breakpoints 1 |
disable breakpoints | 禁⽤所有断点 | disable breakpoints |
enable breakpoints | 启⽤所有断点 | enable breakpoints |
info/i breakpoints | 查看当前设置的断点列表 | info breakpoints |
display 变量名 | 跟踪显⽰指定变量的值(每次停止时) | display x |
undisplay 编号 | 取消对指定编号的变量的跟踪显示 | undisplay 1 |
until X⾏号 | 执⾏到指定⾏号 | until 20 |
backtrace/bt | 查看当前执⾏栈的各级函数调⽤及参数 | backtrace |
info/i locals | 查看当前栈帧的局部变量值 | info locals |
quit | 退出GDB调试器 | quit |
📌
• 上面的基本调试还是麻烦,虽然是黑屏,但是还是想看到代码调试
推荐安装cgdb:
• Ubuntu: sudo apt-get install -y cgdb
• Centos: sudo yum install -y cgdb
执行时监视一个表达式(如变量)的值。如果监视的表达式在程序运行期间的值发生变化,GDB 会暂 停程序的执行,并通知使用者
(gdb) l main
11
12 return result;
13 }
14
15 int main()
16 {
17 int start = 1;
18 int end = 100;
19 printf("I will begin\n");
20 int n = Sum(start, end);
(gdb) b 20
Breakpoint 1 at 0x11c3: file mycmd.c, line 20.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000000011c3 in main at mycmd.c:20
(gdb) r
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:20
20 int n = Sum(start, end);
(gdb) s
Sum (s=32767, e=-7136) at mycmd.c:5
5 {
(gdb) n
6 int result = 0;
(gdb) watch result
Hardware watchpoint 2: result
(gdb) c
Continuing.
Hardware watchpoint 2: result
Old value = -6896
New value = 0
Sum (s=1, e=100) at mycmd.c:7
7 for(int i = s; i <= e; i++)
(gdb) c
Continuing.
Hardware watchpoint 2: result
Old value = 0
New value = 1
Sum (s=1, e=100) at mycmd.c:7
7 for(int i = s; i <= e; i++)
(gdb) c
Continuing.
Hardware watchpoint 2: result
Old value = 1
New value = 3
Sum (s=1, e=100) at mycmd.c:7
7 for(int i = s; i <= e; i++)
(gdb) c
Continuing.
Hardware watchpoint 2: result
Old value = 3
New value = 6
Sum (s=1, e=100) at mycmd.c:7
7 for(int i = s; i <= e; i++)
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
2 hw watchpoint keep y result
breakpoint already hit 4 times
(gdb) d 2
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
(gdb) finish
Run till exit from #0 Sum (s=1, e=100) at mycmd.c:7
0x00005555555551d2 in main () at mycmd.c:20
20 int n = Sum(start, end);
Value returned is $1 = 5050
📌 注意:
更改一下标志位,假设我们想得到 +-result
// mycmd.c
#include <stdio.h>
int flag = 0; // 故意错误
//int flag = -1;
//int flag = 1;
int Sum(int s, int e)
{
int result = 0;
for(int i = s; i <= e; i++)
{
result += i;
}
return result*flag;
}
int main()
{
int start = 1;
int end = 100;
printf("I will begin\n");
int n = Sum(start, end);
printf("running done, result is: [%d-%d]=%d\n", start, end, n);
return 0;
}
(gdb) l main
15
16 return result*flag;
17 }
18
19 int main()
20 {
21 int start = 1;
22 int end = 100;
23 printf("I will begin\n");
24 int n = Sum(start, end);
(gdb) b 24
Breakpoint 1 at 0x11ca: file mycmd.c, line 24.
(gdb) r
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:24
24 int n = Sum(start, end);
(gdb) n
25 printf("running done, result is: [%d-%d]=%d\n", start, end,
n);
(gdb) n
running done, result is: [1-100]=0 # 这⾥结果为什么是0?
26 return 0;
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:24
24 int n = Sum(start, end);
(gdb) s
Sum (s=32767, e=-7136) at mycmd.c:9
9 {
(gdb) n
10 int result = 0;
(gdb) n
11 for(int i = s; i <= e; i++)
(gdb)
13 result += i;
(gdb)
11 for(int i = s; i <= e; i++)
(gdb)
13 result += i;
(gdb) until 14
Sum (s=1, e=100) at mycmd.c:16
16 return result*flag;
(gdb) p result
$1 = 5050
(gdb) p flag
$2 = 0
(gdb) set var flag=1 # 更改flag的值,确认是否是它的原因
(gdb) p flag
$3 = 1
(gdb) n
17 }
(gdb) n
main () at mycmd.c:25
25 printf("running done, result is: [%d-%d]=%d\n", start, end,
n);
(gdb) n
running done, result is: [1-100]=5050 # 是它的原因
26 return 0;
添加条件断点
(gdb) l main
11
12 return result;
13 }
14
15 int main()
16 {
17 int start = 1;
18 int end = 100;
19 printf("I will begin\n");
20 int n = Sum(start, end);
(gdb) b 20
Breakpoint 1 at 0x11c3: file mycmd.c, line 20.
(gdb) r
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:20
20 int n = Sum(start, end);
(gdb) s
Sum (s=32767, e=-7136) at mycmd.c:5
5 {
(gdb) n
6 int result = 0;
(gdb) n
7 for(int i = s; i <= e; i++)
(gdb) n
9 result += i;
(gdb) display i
1: i = 1
(gdb) n
7 for(int i = s; i <= e; i++)
1: i = 1
(gdb) n
9 result += i;
1: i = 2
(gdb) n
7 for(int i = s; i <= e; i++)
1: i = 2
(gdb) n
9 result += i;
1: i = 3
(gdb)
7 for(int i = s; i <= e; i++)
1: i = 3
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
(gdb) b 9 if i == 30 # 9是⾏号,表⽰新增断点的位置
Breakpoint 2 at 0x555555555186: file mycmd.c, line 9.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9
stop only if i == 30
(gdb) finish
Run till exit from #0 Sum (s=1, e=100) at mycmd.c:7
Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9
9 result += i;
1: i = 30
(gdb) finish
Run till exit from #0 Sum (s=1, e=100) at mycmd.c:9
0x00005555555551d2 in main () at mycmd.c:20
20 int n = Sum(start, end);
Value returned is $1 = 5050
给已经存在的端点新增条件
(gdb) l main
11
12 return result;
13 }
14
15 int main()
16 {
17 int start = 1;
18 int end = 100;
19 printf("I will begin\n");
20 int n = Sum(start, end);
(gdb) b 20
Breakpoint 1 at 0x11c3: file mycmd.c, line 20.
(gdb) r
Starting program: /home/whb/test/test/mycmd
I will begin
Breakpoint 1, main () at mycmd.c:20
20 int n = Sum(start, end);
(gdb) s
Sum (s=32767, e=-7136) at mycmd.c:5
5 {
(gdb) n
6 int result = 0;
(gdb) n
7 for(int i = s; i <= e; i++)
(gdb) n
9 result += i;
(gdb)
7 for(int i = s; i <= e; i++)
(gdb)
9 result += i;
(gdb)
7 for(int i = s; i <= e; i++)
(gdb)
9 result += i;
(gdb)
7 for(int i = s; i <= e; i++)
(gdb) b 9 # 我们在第9⾏新增⼀个断点,⽤来开始测试
Breakpoint 2 at 0x555555555186: file mycmd.c, line 9.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9
(gdb) n
Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9
9 result += i;
(gdb) n
7 for(int i = s; i <= e; i++)
(gdb) n
Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9
9 result += i;
(gdb) condition 2 i==30 #给2号断点,新增条件i==30
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00005555555551c3 in main at mycmd.c:20
breakpoint already hit 1 time
2 breakpoint keep y 0x0000555555555186 in Sum at mycmd.c:9
stop only if i==30
breakpoint already hit 2 times
(gdb) n
7 for(int i = s; i <= e; i++)
(gdb) n
9 result += i;
(gdb) c
Continuing.
Breakpoint 2, Sum (s=1, e=100) at mycmd.c:9
9 result += i;
(gdb) p i
$1 = 30
(gdb) p result
$2 = 435
📌 注意: