【Linux】调试工具GDB的使用及案例讲解

news/2025/2/27 9:11:41

Linux系列


文章目录

  • Linux系列
  • 前言
  • 一、gdb的使用背景
  • 二、gdb的使用
  • 总结


本篇主要针对小白讲解,可以很多地方比较咯嗦

前言

GDB是Linux下一款强大的调试工具。GDB可以调试C、C++、Java等语言,对于在Linux下工作的程序员来说,GDB是必不可少的调试工具。

本篇我将以c程序,进行调试和讲解


一、gdb的使用背景

相较于Windows下的VS编译器中的点击调试,gdb调试器因不具备图形化界面,故而只能采用纯命令行的形式进行调试,这样也就意味着学习难度要高于VS.

在学习gdb的使用之前,我们首先要知道,只有【debug】环境下编译的可执行程序才可以被调试,而在Linux中gcc编译器默认编译环境为【release】,要编译生成【debug】版的可执行程序,我们可以使用gcc编译器配合‘-g’选项,生成【debug】文件。

二、gdb的使用

下面为test.c文件中的代码,我接下来使用它讲解,在有不同场景需求时,会进行更换,大家仔细看一下调用逻辑

1 #include<stdio.h>
  2 void func2()
  3 {
  4   printf("Hello Linux\n");
  5 }
  6 void func1()
  7 {
  8   int i,sum=0;
  9   for(i=0;i<10;i++)
 10   {
 11     sum+=i;
 12   }
 13   func2();
 14   printf("这是func1\n");
 15 }
 16 int func(int x)
 17 {
 18   func1();                                                                                                                        
 19   return x+100;
 20 }
 21 int main()
 22 {
 23   int a=0;
 24   printf("%d\n",a);
 25   int b =func(a);
 26   printf("%d\n",b);

下面为Makefile文件中的指令

  1 test:test.c
  2     gcc -o $@ $^ -g
  3 .PHONY:clear
  4 clear:
  5     rm -rf test   

生成【debug】文件开始调试。
进入调试阶段
语法:gdb 可执行程序

在这里插入图片描述
显示代码信息
语法l(list缩写) 行号/函数名-----每次显示十行

在这里插入图片描述
在这里插入图片描述
从上面两次执行结果可以看出,这个指令并不是从我们给的行号开始显示,而是在给的行号的上下一共显示十行。

在这里插入图片描述
指定函数显示。
若想从代码开始行显示,我们只需要‘l 0’即可:
在这里插入图片描述
我们可以看到当第一次执行,第二次再执行就可以不输入指令,直接回车即可,这是因为gdb自动记录最近一条指令.
启动程序
语法:r(run)

在这里插入图片描述
图中为程序执行结果,因为没有设置断点,所以程序执行到结束。
设置断点
语法:b(breakpoint) 行号/函数名----指定在某一行打断点

在这里插入图片描述
这里我在代码的23、25、26行设置了断点。
查看断点
语法:info b

在这里插入图片描述

上面为我们设置的断点信息。

删除指点断点
语法:d 要删除断点编号

在这里插入图片描述
删除全部断点
语法:d breakpoints

在这里插入图片描述
启用/禁用断点
语法:disable 编号-----禁用断点

在这里插入图片描述
这里可以看到,我重新设置的断点编号是从4开始,而不是从1,这是因为我们没有重新启动gdb,所以编号会从上次的编号继续向下。

在这里插入图片描述
对比指令执行前可以发现,【Enb】从y状态变为n状态。
这里依然可以配合breakpoints使用,大家可以自己尝试
语法:enable 编号----启用断点

在这里插入图片描述

调试
语法:n------逐过程调试(不会进入函数体内部)

为了更好的体现这个效果我,我将编号7的断点删除了
在这里插入图片描述
r执行到达第一个断点处。
在这里插入图片描述
此时可以看到程序执行到断点处,并没有进入func函数内部,而是直接向下执行。
语法:s----逐语句调试,会进入调用函数内部
在这里插入图片描述
当使用s执行调试时,程序会进入调用函数内部。
显示/追踪变量信息
语法:p 变量名-----将变量信息显示在显示器上

在这里插入图片描述
也可以配合取地址符,显示变量地址。
在这里插入图片描述
语法:display 变量名 ----追踪显示变量(执行任何一条指令后,都将指定的变量显示出来)

在这里插入图片描述
语法:undisplay 编号------取消常显示
在这里插入图片描述
刚刚取消了忘截图,又重新设置的,所以编号变为了2
此时再执行其他指令,i就不会常显示了。
查看函数调用
语法:bt----可以看到函数逐级调用的过程

在这里插入图片描述
将上图和我们调试的代码结合起来可以看出,bt命令显示出的编号,和我们代码逻辑中函数调用顺序是相反的,而这种情况就是一个压栈的过程。你可以自己尝试,整个函数调用链都是遵循这个逻辑的,所以我们就可以使用这个命令来查看栈帧的创建情况。
修改变量值
语法:set var 变量名=指定值

例如:当我们在一个循环中,想查看当i=1000时的情况,而让程序一点一点跑就太麻烦了,这是我们就可以使用这个命令,进行指定设置。

for(i=0;i<10;i++)
	{
	  sum+=i;
	}

在这里插入图片描述
可以看到我们通过指令,直接将i的值设置为了5.
指定行调转
语法:until 行号-----------这里的行号指的是,代码所处行

在这里插入图片描述
当前调试程序执行至第九行。

1	#include<stdio.h>
2	void func2()
3	{
4	  printf("Hello Linux\n");
5	}
6	void func1()
7	{
8	  int i,sum=0;
9	  for(i=0;i<10;i++)
10	  { 
11	    sum+=i;
12	  }
13	  func2();
14	  printf("这是func1\n");
15	}
16	int func(int x)
17	{
18	  func1();
19	  return x+100;
20	}
21	int main()
22	{
23	  int a=0;
24	  printf("%d\n",a);
25	  int b =func(a);
26	  printf("%d\n",b);
27	  return 0;
28	}


我们直接程序跳转的13行处,执行func2函数:
在这里插入图片描述
强制执行函数
语法:finish--------强制执行所处函数,并返回到调用该函数的位置

为了演示,我们重新开始调试。
在这里插入图片描述
此时函数执行至func1函数,我们使用命令将该函数强制执行完。
在这里插入图片描述
可以看到此时,程序将func1函数强制执行完毕,并返回至调用处等待指令。
跳过结点
语法:c--------当我们在调试时,想要从一个断点直接跳转到下一个断点想对断,可以使用这个命令

在这里插入图片描述大家结合上面代码的调用逻辑分析

这是当前所设置的断点,我期望从23行代码,直接运行至8行,中间的程序不让他显示的执行。(这是使用n或s命令无法办到的)
在这里插入图片描述

总结

当大家对指令比较熟悉时,gdb的使用还是比较简单的,以上是我个人,经常使用的命令,是对标VS下编译的调试功能来介绍的,如果这不能满足你的要求,可以搜一些更高级的用法。


http://www.niftyadmin.cn/n/5869853.html

相关文章

数据存储:一文掌握存储数据到MongoDB详解

文章目录 一、环境准备1.1 安装MongoDB1.2 安装Python MongoDB驱动 二、连接到MongoDB2.1 基本连接2.2 连接到MongoDB Atlas&#xff08;云服务&#xff09; 三、基本CRUD操作3.1 创建&#xff08;Create&#xff09;&#xff1a;插入数据3.2 读取&#xff08;Read&#xff09;…

【学习方法】学习软件专业课程的思考方式

学习软件专业课程的思考方式 在学习软件专业课程时&#xff0c;我们往往会遇到一些看似简单但实际上却非常复杂的概念和理论。这种时候&#xff0c;我们可能会觉得书本很厚&#xff0c;难以理解。然而&#xff0c;这种看似简单的想法并不一定就是错误的&#xff0c;因为它激发…

去中心化技术P2P框架

中心化网络与去中心化网络 1. 中心化网络 在传统的中心化网络中&#xff0c;所有客户端都通过一个中心服务器进行通信。这种网络拓扑结构通常是一个星型结构&#xff0c;其中服务器作为中心节点&#xff0c;每个客户端只能与服务器通信。如果客户端之间需要通信&#xff0c;必须…

ElasticSearch 是如何实现分布式的?

ElasticSearch 是如何实现分布式的&#xff1f; 如果你正在准备技术面试&#xff0c;或者想深入理解 ElasticSearch&#xff08;简称 ES&#xff09;是如何实现分布式的&#xff0c;这篇文章将用通俗易懂的方式来讲解。 1. 为什么需要分布式搜索&#xff1f; 在互联网行业&a…

【Python爬虫(80)】当Python爬虫邂逅边缘计算:探索数据采集新境界

【Python爬虫】专栏简介&#xff1a;本专栏是 Python 爬虫领域的集大成之作&#xff0c;共 100 章节。从 Python 基础语法、爬虫入门知识讲起&#xff0c;深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑&#xff0c;覆盖网页、图片、音频等各类数据爬取&#xff…

AWS S3 如何设置公开访问权限?

1.让整个bucket都有公开访问权限 1.1关闭【阻止公共读】 1.2关闭ACL访问控制 1.3打开桶策略 这样桶内所有的图片就能访问了 2.只开放特定文件让其具有访问权限&#xff1f; 2.1关闭【阻止公共读】 如之前的图示 2.2打开ACL控制 2.3单个文件打开公共读

SOC-ATF 安全启动BL31流程分析(3)

一、BL31启动流程 与bl1和bl2不同&#xff0c;bl31包含两部分功能&#xff0c;在启动时作为启动流程的一部分&#xff0c;执行软硬件初始化以及启动bl32和bl33镜像。在系统启动完成后&#xff0c;将继续驻留于系统中&#xff0c;并处理来自其它异常等级的smc异常&#xff0c;以…

Element Plus: el-card的内容滚动问题

问题 由于el-card的body div默认没有设置的height&#xff0c;因此它里面的内容高度超出后不能滚动。如下图所示&#xff1a; 方案 通过body-style&#xff08;也可以使用body-class&#xff09;设置height。如下图所示&#xff1a;