【Linux】工具Gdb调试轻度使用(C++)

目录

一、Gdb背景

二、Gdb基本命令

[【2.1】list | l](#【2.1】list | l)

[【2.2】break | b](#【2.2】break | b)

[【2.5】delete | d](#【2.5】delete | d)

【2.6】disable

【2.7】enable

【2.3】info

[【2.4】info locals](#【2.4】info locals)

[【2.6】run | r](#【2.6】run | r)

[【2.7】next | n](#【2.7】next | n)

[【2.8】step | s](#【2.8】step | s)

[【2.9】 continue | c](#【2.9】 continue | c)

【2.10】bt

【2.11】finish

三、Gdb查看变量

【3.1】p

【3.2】display

【3.2】undisplay

【3.3】until

[【3.4】set var](#【3.4】set var)


一、Gdb背景

  • 程序的发布方式有两种,debug模式和release模式

  • Linux gcc/g++出来的二进制程序,默认是release模式。

  • 要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项 。

cpp 复制代码
// 查看可执行程序的指令:
readelf -S progressBar
readelf -S progressBar | grep debug

二、Gdb基本命令

【2.1】list | l

显示当前函数中的代码。

cpp 复制代码
列出当前函数中代码。

// 命令:
list [函数名]
l    [函数名]
(gdb) list 0                                // 显示行命令.
1   #include "ProgressBar.h"
2   
3   int main(){
4       ProgressBar();  // 进度条函数调用.
5       return 0;
6   }
(gdb) 
​
-----------------------------------------------------------------------------------------
​
(gdb) list ProgressBar                      // 显示指定函数.
1   #include "ProgressBar.h"
2   
3   // 进度条函数实现.
4   void ProgressBar(){
5       // 进度条存储区.
6       char arrBar[NUM];     
7       // 进度条存储区初始化.
8       memset(arrBar, '\0', sizeof(arrBar)); 
9       const char* flag = "|\\-/";
10      char style[STYLE_NUM] = {'+', '=', '*', '>', '#'};
(gdb)                                       // 回车继续显示
11  
12      for(int i = 0; i <= 100; i++){
13          printf("[%-100s][%2d%%][%c]\r", arrBar, i, flag[i % 4]);
14          fflush(stdout);             // 立即打印刷新.
15          
16          arrBar[i] = style[N];          // 存入打印风格的字符.
17          usleep(10000);              // 休眠以微妙为单位.
18      }
19      printf("\n");
20  }

【2.2】break | b

设置断点。

cpp 复制代码
// 命令:
break 行号
b     行号


(gdb) b 6                           // Main.c中main函数第6行打断点
Breakpoint 4 at 0x40066b: file Main.c, line 6.          
(gdb) b 7                           // ProgressBar.c中ProgressBar函数第7行打断点
Breakpoint 5 at 0x400684: file ProgressBar.c, line 7.
    
(gdb) info b                        // 查看已设置的断点
Num     Type           Disp Enb Address            What
4       breakpoint     keep y   0x000000000040066b in main at Main.c:6
5       breakpoint     keep y   0x0000000000400684 in ProgressBar at ProgressBar.c:7

【2.5】delete | d

删除断点。

cpp 复制代码
// 命令:
delete [断点编号]       // 删除断点
d      [断点编号]       // 删除断点


(gdb) info break                // 查看断点
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040066b in main at Main.c:6
2       breakpoint     keep y   0x0000000000400684 in ProgressBar at ProgressBar.c:7
(gdb) d 1                       // 删除编号为1的断点
(gdb) info break                // 查看断点
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x0000000000400684 in ProgressBar at ProgressBar.c:7
(gdb) delete 2                  // 删除编号为2的断点
(gdb) info break                // 查看断点
No breakpoints or watchpoints.
    
// 下面直接输入d删除所有的断点
(gdb) info b                    // 查看断点
Num     Type           Disp Enb Address            What
5       breakpoint     keep y   0x000000000040066b in main at Main.c:6
6       breakpoint     keep y   0x0000000000400684 in ProgressBar at ProgressBar.c:7
(gdb) d                         // 删除所有的断点
Delete all breakpoints? (y or n) y
(gdb) info b                    // 查看断点
No breakpoints or watchpoints.

【2.6】disable

禁用断点。

cpp 复制代码
// 命令:
disable     [断点编号]


(gdb) info b                // 显示所有设置的断点
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040066b in main at Main.c:6
2       breakpoint     keep y   0x0000000000400684 in ProgressBar at ProgressBar.c:7
(gdb) disable 1             // 禁用断点
(gdb) info b                // 显示所有设置的断点 Enb 变成了n
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x000000000040066b in main at Main.c:6
2       breakpoint     keep y   0x0000000000400684 in ProgressBar at ProgressBar.c:7

【2.7】enable

启动断点。

cpp 复制代码
// 命令:
enable      [断点编号]


(gdb) info b                // 显示所有设置的断点
Num     Type           Disp Enb Address            What
1       breakpoint     keep n   0x000000000040066b in main at Main.c:6
2       breakpoint     keep y   0x0000000000400684 in ProgressBar at ProgressBar.c:7
(gdb) enable 1              // 使能断点
(gdb) info b                // 显示所有设置的断点 Enb 变成了y
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040066b in main at Main.c:6
2       breakpoint     keep y   0x0000000000400684 in ProgressBar at ProgressBar.c:7

【2.3】info

查看断点。

cpp 复制代码
// 命令:
info break  // 查看断点
info b      // 查看断点


(gdb) info b                        // 显示已设置的断点
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040066b in main at Main.c:6
2       breakpoint     keep y   0x0000000000400684 in ProgressBar at ProgressBar.c:7
(gdb) info break                    // 显示已设置的断点
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040066b in main at Main.c:6
2       breakpoint     keep y   0x0000000000400684 in ProgressBar at ProgressBar.c:7

【2.4】info locals

显示当前堆栈局部变量的值。

cpp 复制代码
// 命令:
 info locals


// -- 在ProgressBar()函数中
(gdb) info locals
bar = "####", '\000' <repeats 46 times>, "##", '\000' <repeats 48 times>
cnt = 52
style = "+=>#."
lable = 0x4007c0 "|\\-/"

【2.6】run | r

运行。

cpp 复制代码
// 指定:
run             // 直接运行
r               // 直接运行


(gdb) r                     // 运行程序
Starting program: /home/shaxiang/CodeDemo/Linux/ProgressBar/progressBar 
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64
[####################################################################################################][100%][|]
[Inferior 1 (process 16045) exited normally]
(gdb) run                   // 运行程序
Starting program: /home/shaxiang/CodeDemo/Linux/ProgressBar/progressBar 
[####################################################################################################][100%][|]
[Inferior 1 (process 16091) exited normally]

【2.7】next | n

逐过程调试。

cpp 复制代码
// 指令:
next            // 逐过程运行
n               // 逐过程运行


Breakpoint 7, main () at Main.c:6
6     ProgressBar();                    // 在断点处停下来
(gdb) n                                 // 逐过程运行
​
Breakpoint 8, ProgressBar () at ProgressBar.c:7
7       memset(bar, '\0', sizeof(bar));
(gdb) n                                 // 逐过程运行
9       int cnt = 0;
(gdb) n                                 // 逐过程运行
11      const char* lable = "|\\-/";
(gdb) n                                 // 逐过程运行
12      while(cnt <= 100)
(gdb) n                                 // 逐过程运行
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);

【2.8】step | s

逐语句调试。

cpp 复制代码
// 指令:
step            // 逐语句运行
s               // 逐语句运行


Breakpoint 7, main () at Main.c:6
6     ProgressBar();                    // 在断点处停下来
(gdb) s                                 // 逐语句运行
​
Breakpoint 8, ProgressBar () at ProgressBar.c:7
7       memset(bar, '\0', sizeof(bar));
(gdb) s                                 // 逐语句运行
9       int cnt = 0;
(gdb) s                                 // 逐语句运行
11      const char* lable = "|\\-/";
(gdb) s                                 // 逐语句运行
12      while(cnt <= 100)
(gdb) s                                 // 逐语句运行
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);

【2.9】 continue | c

运行到下一个断点。

cpp 复制代码
// 指令:
continue            // 运行到下一个断点
c                   // 运行到下一个断点


12      while(cnt <= 100)
(gdb) s                                 // 逐语句运行
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);
(gdb) s                                 // 逐语句运行
15          fflush(stdout); // 将数据立马刷新到缓冲区
(gdb) s                                 // 逐语句运行
17####          bar[cnt++] = style[S];                                                               ][ 5%][\]
(gdb) s                                 // 逐语句运行
18          usleep(50000);
(gdb) c                                 // 运行到下一个断点
Continuing.
[####################################################################################################][100%][|]
[Inferior 1 (process 17750) exited normally]

【2.10】bt

查看堆栈。

cpp 复制代码
// 命令:
bt                  // 查看堆栈


(gdb) r                             // 运行
Starting program: /home/shaxiang/CodeDemo/Linux/ProgressBar/progressBar 
​
Breakpoint 7, main () at Main.c:6
6     ProgressBar();                // 在断点处停下来
(gdb) s                             // 逐语句运行
​
Breakpoint 8, ProgressBar () at ProgressBar.c:7
7       memset(bar, '\0', sizeof(bar));
(gdb) bt                            // 查看堆栈
#0  ProgressBar () at ProgressBar.c:7
#1  0x0000000000400675 in main () at Main.c:6

【2.11】finish

直接运行完函数。

cpp 复制代码
// 命令:
finish          // 运行完函数


(gdb) r                             // 运行程序
Starting program: /home/shaxiang/CodeDemo/Linux/ProgressBar/progressBar 
​
Breakpoint 7, main () at Main.c:6
6     ProgressBar();                // 在断点处停下来
(gdb) s                             // 逐语句运行
​
Breakpoint 8, ProgressBar () at ProgressBar.c:7
7       memset(bar, '\0', sizeof(bar));
(gdb) finish                        // 运行到函数后,直接运行完当前的函数
Run till exit from #0  ProgressBar () at ProgressBar.c:7
[####################################################################################################][100%][|]
main () at Main.c:8
8     return 0;
复制代码

三、Gdb查看变量

【3.1】p

查看变量的值。

cpp 复制代码
p [变量名]             // 查看该变量的值


12      while(cnt <= 100)                   // while循环中运行
(gdb) s
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);
(gdb) s
15          fflush(stdout); // 将数据立马刷新到缓冲区
(gdb) s
17              bar[cnt++] = style[S];                                                               ][ 1%][\]
(gdb) s
18          usleep(50000);
(gdb) s
12      while(cnt <= 100)
(gdb) s
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);
(gdb) s
15          fflush(stdout); // 将数据立马刷新到缓冲区
(gdb) s
17#             bar[cnt++] = style[S];                                                               ][ 2%][-]
(gdb) s
18          usleep(50000);
(gdb) p cnt                     // 查看p的值
$2 = 3

【3.2】display

跟踪查看变量的值。

cpp 复制代码
// 命令:
display     [变量名]


(gdb) display cnt               // 跟踪cnt这个变量监控值的变化 (display &cnt 这样可以查看地址)
1: cnt = 5
(gdb) s
12      while(cnt <= 100)
1: cnt = 5
(gdb) s
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);
1: cnt = 5
(gdb) s
15          fflush(stdout); // 将数据立马刷新到缓冲区
1: cnt = 5
(gdb) s
17####          bar[cnt++] = style[S];                                                               ][ 5%][\]
1: cnt = 5
(gdb) s
18          usleep(50000);
1: cnt = 6
​

【3.2】undisplay

取消跟踪查看变量的值。

cpp 复制代码
// 命令:
undisplay   [变量名]


(gdb) undisplay 1           // 取消跟踪cnt这个变量监控值的变化
(gdb) s
12      while(cnt <= 100)
(gdb) s
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);
(gdb) s
15          fflush(stdout); // 将数据立马刷新到缓冲区
(gdb) s
17#####         bar[cnt++] = style[S];                                                               ][ 6%][-]
(gdb) s
18          usleep(50000);
​

【3.3】until

跳转指定行。

cpp 复制代码
// 指令:
until       [行号]            // 跳转行号


12      while(cnt <= 100)           // 循环运行
(gdb) s
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);
(gdb) s
15          fflush(stdout); // 将数据立马刷新到缓冲区
(gdb) s
17######        bar[cnt++] = style[S];                                                               ][ 9%][\]
(gdb) s
18          usleep(50000);
(gdb) s
12      while(cnt <= 100)           // 循环运行
(gdb) s
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);
(gdb) s
15          fflush(stdout); // 将数据立马刷新到缓冲区
(gdb) s
17######        bar[cnt++] = style[S];                                                               ][10%][-]
(gdb) s
18          usleep(50000);
​
(gdb) until 20                  // 跳转到指定的行
ProgressBar () at ProgressBar.c:20###################################################################][100%][|]
20      printf("\n");

【3.4】set var

设定指定的值。

cpp 复制代码
// 指定
set var     [变量名]           // 设定指定的变量的值。


12      while(cnt <= 100)
2: cnt = 4
(gdb) s
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);
2: cnt = 4
(gdb) s
15          fflush(stdout); // 将数据立马刷新到缓冲区
2: cnt = 4
(gdb) s
17###           bar[cnt++] = style[S];                                                               ][ 4%][|]
2: cnt = 4
(gdb) set var cnt=50                // 设定指定的变量值!!!!!!
(gdb) s
18          usleep(50000);
2: cnt = 51
(gdb) s
12      while(cnt <= 100)
2: cnt = 51
(gdb) s
14          printf("[%-100s][%2d%%][%c]\r", bar, cnt, lable[cnt % 4]);
2: cnt = 51
(gdb) s
15          fflush(stdout); // 将数据立马刷新到缓冲区
2: cnt = 51
(gdb) s
17###           bar[cnt++] = style[S];                                                               ][51%][/]
2: cnt = 51
(gdb) s
18          usleep(50000);
2: cnt = 52
相关推荐
蜜獾云2 分钟前
docker 安装雷池WAF防火墙 守护Web服务器
linux·运维·服务器·网络·网络安全·docker·容器
小屁不止是运维3 分钟前
麒麟操作系统服务架构保姆级教程(五)NGINX中间件详解
linux·运维·服务器·nginx·中间件·架构
bitcsljl16 分钟前
Linux 命令行快捷键
linux·运维·服务器
ac.char19 分钟前
在 Ubuntu 下使用 Tauri 打包 EXE 应用
linux·运维·ubuntu
Cachel wood38 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Youkiup1 小时前
【linux 常用命令】
linux·运维·服务器
qq_297504611 小时前
【解决】Linux更新系统内核后Nvidia-smi has failed...
linux·运维·服务器
weixin_437398211 小时前
Linux扩展——shell编程
linux·运维·服务器·bash
小燚~1 小时前
ubuntu开机进入initramfs状态
linux·运维·ubuntu
小林熬夜学编程1 小时前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http