GDB调试实验

news2024/12/24 8:37:16

一、实验准备

在 Linux 环境软件开发中,GDB 是调试 C 和 C++ 程序的主要工具。本次实验围绕着GDB常用的调试操作进行。

1、设置断点的意义

当我们想查看变量内容,堆栈情况等等,可以指定断点。程序执行到断点处会暂停执行。break 命令用来设置断点,缩写形式为b。设置断点后,以便我们更详细的跟踪断点附近程序的执行情况。

2、C源代码准备

//test.c
#include <stdio.h>
 
void judge(int num){

	if ((num & 1) == 0){
		printf("%d is even\n",num);
		return;
	}else{
		printf("%d is odd\n",num);
		return;
	}
}
 
int main(int argc, char *argv[]){
    
	judge(0);
	judge(1);
	judge(4);

	return 0;
}

注意:要调试C/C++的程序,首先在编译时,要使用gdb调试程序,在使用gcc编译源代码时必须加上“-g”参数。保留调试信息,否则不能使用GDB进行调试。

gcc -g test.c -o test


 二、实验内容

1、通过行号设置断点

break [行号]    或简写为   b [行号]

break 行号,断点设置在该行开始处,注意:该行代码未被执行

如果有多个源文件的话,也可以使用“文件名:行号”的形式设置断点。示例如下:

上图中的(gdb) b test.c:18是设置了断点。断点的位置是test.c文件的18行。使用r命令执行脚本时,当运行到18行时就会暂停。注意:该行代码未被执行。

2、通过函数设置断点

 break [函数名]    或简写为    b [函数名]

break 函数名,断点设置在该函数的开始处,断点所在行未被执行:

如果按上面的方法设置断点后,每次执行到断点位置都会暂停。然而,有时候我们只想在指定条件下才暂停。这时候可以根据条件设置断点。设置条件断点的形式,就是在设置断点的基本形式后面增加if条件。示例如下:

b 6 if num > 0

此时,只有当num>0时,程序才会在第6行断住。

3、查看断点信息

 info breakpoints  或简写为  info b

可以使用info breakpoints查看断点的相关信息。包含都设置了哪些断点,断点被命中的次数等信息。示例如下:

使用info breakpoints命令后,将会列出所有已设置的断点,每一个断点都有一个标号,用来代表这个断点。

4、删除断点

delete breakpoint  或简写为  del breakpoint

对于不再使用的断点我们可以将其删除。删除的命令格式为 delete breakpoint 断点编号。info breakpoint命令显示结果中的num列就是编号。删除断点的示例如下:

(看样子还不能简写为b,哈哈),再来看一种有多个断点的情况

不指定断点编号的话,默认删除全部断点(会有confirm提示的,别担心hh~) 

5、查看源码

断点设置完后,当程序运行到断点处就会暂停。暂停的时候,我们可以查看断点附近的代码。查看代码的命令是list,缩写形式为l(L的小写字母)。

因为上面设置的断点是judge(1),所以list会展示出judge(1)附近的代码,再次执行list,会将后面的代码展示出来,直到代码全部展示完毕。ps:我数了一下,应该是每次展示附近的10行代码。

6、指定行号查看代码

 list first,last   或简写为   l first,last  # 小写的L

7、列出指定文件的源码

前面执行list命令时,默认列出test.c的源码,如果想要看指定文件的源码呢?可以使用下面的指令

list  文件名+行号/函数名

 


断点附近的代码了解之后,这时候就可以使用单步执行一条一条语句的去执行。可以随时查看执行后的结果。接下来你可能会想知道程序运行的一些情况,就需要查看变量的值。下面介绍单步调试与设置变量。

8、单步调试

单步执行有两个命令,分别是step和next。我们可能打了多处断点,或者断点打在循环内,这个时候,可以使用continue命令。这三个命令的区别在于:

1、next命令(可简写为n)用于在程序断住后,继续执行下一条语句。
2、step命令(可简写为s),它可以单步跟踪到函数内部。
3、continue命令(可简写为c)或者fg,它会继续执行程序,直到再次遇到断点处。

单步进入-step

step 一条语句一条语句的执行。它有一个别名s。它可以单步跟踪到函数内部。详细来讲,step 就是单步执行,遇到子函数就进入并且继续单步执行;在其他调试其中相当于step-into命令,作用是移动到下一个可执行的代码行。如果当前行是一个函数调用,则调试器进入函数并停止在函数体的第一行。step可以帮助初步揭开代码位置的谜团,例如:函数调用和函数本身可能在不同的文件中。

我在第18行打了断点,然后执行run命令,到18行断点处停下,然后用step命令进入judge函数内部,step 就是单步执行,遇到子函数就进入并且继续单步执行,比如在源程序第6行没有函数调用,只是一个if判断,所以执行step就会继续向下走,而如果该行有函数调用,比如printf,继续执行step就会深入到printf函数里面,如果我们想从printf库函数中跳出来,可以执行finish命令。

finish就是单步执行到子函数内时,用step out就可以执行完子函数余下部分,并返回到上一层函数。在其他调试器中相当于step-out,作用是在栈中前进到到下一层,并在调用函数的下一行停止。

单步执行-next

next命令(可简写为n)用于在程序断住后,继续执行下一条语句。详细来讲,next 是在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完再停止,也就是把子函数整个作为一步。在其他调试器中相当于step-over,作用是在同一个调用栈层中移动到下一个可执行的代码行。调试器不会进入函数体。如果当前行是函数的最后一行,则,next将进入下一个栈层,并在调用函数的下一行停止。

由上图我们可以看出,next指令不会进入judge函数内部,而是将子函数judge整个执行完再停止,也就是把子函数整个作为一步。

继续执行到下一个断点-continue

我们可能打了多处断点,或者断点打在循环内,若想跳过这个断点,甚至跳过多次断点继续执行该怎么做呢?可以使用continue命令。它的作用就是从暂停处继续执行。命令的简写形式为c。

我把断点打在了子函数judge,函数体的开始位置,因为在主函数中要三次调用子函数judge,相当于打了三个断点,执行continue命令后,就会跳到下一处的断点位置。

跳过执行–skip

在下图可以看到,使用skip之后,将不会进入judge函数。好处就是skip可以在step时跳过一些不想关注的函数或者某个文件。

可以看到,再使用skip之后,使用step将不会进入judge函数。

  • skip delete [num] 删除skip
  • skip enable [num] 使能skip
  • skip disable [num] 去使能skip

其中num是前面通过info skip看到的num值,上面可以带或不带该值,如果不带num,则针对所有skip,如果带上了,则只针对某一个skip。


为方便在终端查看下面讲述的内容,我们换一个源程序文件(如下所示)

#include<stdio.h>
#include<stdlib.h>
 
int main( int argc , char *argv[] )  
{
    int a = 1;
    int i = 0;
    int b[3] = {0,1,2};
    for(i = 0; i < 3;i++)
        b[i] = b[i] + 1;
    printf("%d\n",a);
    int *p;
    p = b;
    printf("%d\n",p[0]);
    return 0;
}

编译产生可执行文件main: 

gcc -g main.c -o main

9、查看变量

打印基本类型变量,数组 

上面讲述了如何设置断点,查看断点附近的代码,并可以单步执行和继续执行。接下来可能会想知道程序运行的一些情况,如查看变量的值。此时我们可以使用print命令,以帮助我们进一步定位问题。

print  [变量名]    或简写为    p  [变量名]

若多个函数或者多个文件有同一个变量名,这个时候可以在前面加上函数名或者文件名来区分:

打印指针指向内容

如果还是使用上面的方式打印指针指向的内容,那么打印出来的只是指针地址,例如: 

而如果想要打印指针指向的内容,需要解引用:

从上面可以看到,仅仅使用*只能打印第一个值,如果要打印多个值,后面跟上@并加上要打印的长度。

另外值得一提的是,$可表示上一个变量,而假设此时有一个链表linkNode,它有next成员代表下一个节点,则可使用下面方式不断打印链表内容:

(gdb)  p *linkNode
( 这里显示linkNode节点内容 )
(gdb)  p *$.next
( 这里显示linkNode节点下一个节点的内容 )

10、按照特定格式打印变量

对于简单的数据,print默认的打印方式已经足够了,它会根据变量类型的格式打印出来,但是有时候这还不够,我们需要更多的格式控制。常见格式控制字符如下:

  • x 按十六进制格式显示变量。
  • d 按十进制格式显示变量。
  • u 按十六进制格式显示无符号整型。
  • o 按八进制格式显示变量。
  • t 按二进制格式显示变量。
  • a 按十六进制格式显示变量。
  • c 按字符格式显示变量。
  • f 按浮点数格式显示变量。

如果我们要查看b数组的十六进制和二进制格式打印,根据上面的规则得到:

 

查看内存内容

使用examine命令(简写为x)来查看内存地址中的值。x命令的语法如下:

x/[n][f][u] addr

其中:

  • n 表示要显示的内存单元数,默认值为1
  • f 表示要打印的格式,前面已经提到了格式控制字符
  • u 要打印的单元长度
  • addr 内存地址

单元类型常见有如下:

  • b 字节
  • h 半字,即双字节
  • w 字,即四字节
  • g 八字节

我们通过一个实例来看,假如我们要把int变量a按照二进制方式打印,并且打印单位是一字节: 

查看寄存器内容

info registers  


以上是对GDB调试做了简单的实验总结,本实验涉及到GDB调试的常见用法,了解这些之后能够使用GDB定位大部分问题。但是GDB的使用远不止如此,当遇到更加复杂的情况时,可以再去学习更多相关操作。

本次实验的完成参考了许多其他博主的博客,笔者在此向各位致谢,感谢各位精彩的分享,让我受益匪浅。

参考链接:

GDB调试指南(入门,看这篇够了)_程序猿编码的博客-CSDN博客

GDB调试入门指南 - 知乎

【Linux】GDB调试教程(新手小白)_gdb p_爪可摘星辰的博客-CSDN博客

 gdb中查看内存方法总结_gdb看的是物理内存还是虚拟内存_angus_monroe的博客-CSDN博客

https://www.cnblogs.com/J1ac/p/9113669.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/445482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React 条件渲染组件

组件通常需要根据不同的条件显示不同的内容&#xff0c;以及根据应用的状态变化只渲染其中的一部分。 在 React 中&#xff0c;可以使用 JavaScript 语法有条件地呈现 JSX&#xff0c;比如 if 语句、&&和 ?: 操作符。 根据条件返回 JSX Demo.js 文件&#xff1a; …

【高危】vm2 <3.9.17 沙箱逃逸漏洞(POC)(CVE-2023-30547 )

漏洞描述 vm2 是一个基于 Node.js 的沙箱环境&#xff0c;可以使用列入白名单的 Node 内置模块运行不受信任的代码。 由于 CVE-2023-29199 的修复不完整&#xff0c;vm2 3.9.17 之前版本的 transformer.js 文件中的 transformer 函数异常处理逻辑存在缺陷。攻击者可以利用这个…

【01-Java Web先导课】-如何进行JDK的安装(或Java环境的配置)

文章目录 一、JDK&#xff08;jdk-8u371-windows-x64.exe&#xff09;的下载1、下载网址2、选择相应版本进行下载 二、JDK&#xff08;jdk-8u371-windows-x64.exe&#xff09;的安装1、JDK安装2、系统环境变量配置3、classspath环境变量设置 免责说明 一、JDK&#xff08;jdk-8…

❤echarts 南丁格尔玫瑰图的使用以及南丁格尔玫瑰图详细配置

❤echarts 南丁格尔玫瑰图的使用以及南丁格尔玫瑰图详细配置 1、认识 使用可以参考之前文章&#xff0c;会使用直接跳过1 引入官网的南丁格尔玫瑰图效果如下&#xff1a; 使用函数配置分为三个部分&#xff1a;初始化> 设置配置> 地图使用参数 配置代码如下 option…

法学考生必看—外经贸法学专业在职研究生

法学专业就业面比较广&#xff0c;但很多人工作后都觉得还是缺少核心竞争力&#xff0c;想通过读研来改变现状&#xff0c;23考研已经落幕&#xff0c;想要今年就能入班学习的院校有吗&#xff1f;有法学专业的吗&#xff1f; 一、学校介绍 对外经济贸易大学创建于1951年&…

STM32 USB资料整理

CypressUSB中文文档 https://img.anfulai.cn/bbs/90026/AN57294%20USB%20101%20An%20Introduction%20to%20Universal%20Serial%20Bus%202.0%20(Chinese).pdf RL-USB教程 https://www.armbbs.cn/forum.php?modviewthread&tid99710 USB应用实战教程第3期&#xff1a;手把…

Java Jvm中的垃圾回收机制

jvm的垃圾回收机制是什么 jvm的垃圾回收机制是GC&#xff08;Garbage Collection&#xff09;&#xff0c;也叫垃圾收集器。 GC基本原理&#xff1a;将内存中不再被使用的对象进行回收&#xff1b;GC中用于回收的方法称为收集器&#xff0c;由于GC需要消耗一些资源和时间&…

认识BASH这个Shell

文章目录 认识BASH这个Shell硬件、内核与shell为什么要学命令行模式的Shell&#xff1f;Bash Shell的功能命令与文件补全(TAB)命令别名设置(alias)历史命令(history)任务管理、前台、后台控制(jobs&#xff0c;fg&#xff0c;bg)通配符程序化脚本 查询命令是否为Bash shell 的内…

前端--移动端布局--2移动开发之flex布局

目标&#xff1a; 能够说出flex盒子的布局原理 能够使用flex布局的常用属性 能够独立完成携程移动端首页案例 目录&#xff1a; flex布局体验 flex布局原理 flex布局父项常见属性 flex布局子项常见属性 写出网首页案例制作 1.flex布局体验 1.1传统布局与flex布局 传…

nacos 部署 配置

文章目录 一、Nacos简介 1、为什么叫Nacos2、Nacos是什么3、能干嘛4、去哪下二、安装并运行Nacos 2.1 基础环境及配置&#xff1a;三、Nacos作为服务注册中心演示 3.1 基于Nacos的服务提供者 2、POM文件3、YML文件4、主启动5、业务类6、测试7、nacos控制台3.2 基于Nacos的服务消…

[POJ - 1080 ]Palindrome(区间DP)

[POJ - 1080 ]Palindrome&#xff08; 区间DP&#xff09; 1、问题2、分析状态表示状态转移空间优化 3、代码 1、问题 给定一个字符串&#xff0c;通过添加最少的字符&#xff0c;使得这个字符串成为一个回文字符串。 2、分析 状态表示 f [ i ] [ j ] f[i][j] f[i][j]表示将…

2023年产品经理需要考的证书,NPDP含金量真高

产品经理国际资格认证NPDP是新产品开发方面的认证&#xff0c;集理论、方法与实践为一体的全方位的知识体系&#xff0c;为公司组织层级进行规划、决策、执行提供良好的方法体系支撑。 【认证机构】 产品开发与管理协会&#xff08;PDMA&#xff09;成立于1979年&#xff0c;是…

盖子的c++小课堂——第十七讲:递归

前言 通知一下&#xff0c;以后每周不定期更新&#xff0c;有可能是周六更新&#xff0c;也可能是周日吧&#xff0c;反正会更新的~~还有我新出的专栏《跟着盖子读论语》&#xff0c;记得订阅一下啊跟着盖子学《论语》_我叫盖子的盖鸭的博客-CSDN博客 三元表达式 三元表达式…

单链表中二级指针的使用以及单链表的增删查改操作

前言&#xff1a;在链表的构建中,链表的初始化和销毁为何需要使用一个二级指针,而不是只需要传递一个指针就可以了,其问题的关键就在于c语言的参数传递的方式是值传递 那么,这篇文章就来聊一聊在链表的初始化中一级指针的传递和二级指针的区别&#xff0c;并总结给出单链表的C语…

AutoCAD使用技巧

AutoCAD使用技巧 环境说明AutoCAD 导入EXCELAutoCAD移动对象到原点 环境说明 本文基于AutoCAD 2021版本。 AutoCAD 导入EXCEL 如果菜单栏隐藏点击显示菜单栏&#xff1a; 在excel中选中copy内容赋值&#xff0c;AutoCAD中选择&#xff1a;编辑-选择性粘贴-作为AutoCAD图元…

必用WhatsApp营销的4个理由

WhatsApp是世界上最受欢迎的消息传递应用程序。每天有1万新用户加入WhatsApp。各种规模的公司都利用该平台与世界各地的客户进行有效的沟通&#xff0c;这要归功于其广泛的覆盖范围、用户友好的设计和安全的端到端加密。因此&#xff0c;WhatsApp聊天机器人迅速普及。 1.为您的…

Kotlin的出现无疑是为了超越Java而存在

Kotlin的出现无疑是为了超越Java而存在。在Google I/O 2017中&#xff0c;Google 宣布 Kotlin 成为 Android 官方开发语言&#xff0c;背景就是Oracle告Google侵权使用java。众所周知&#xff0c;Java的跨平台的开发语言&#xff0c;得益于虚拟机。我比较关注Kotlin用于Android…

Python 使用pipreqs命令生成 `requirements.txt`报错

Python 使用pipreqs命令生成 requirements.txt报错&#xff1a;Fatal error in launcher: Unable to create process using ‘“E:\Anaconda\python.exe” “D:\Anaconda\Scripts\pipreqs.exe” ./ --encodingutf-8’: ??? 问题描述—Python 使用pipreqs命令生成 requireme…

47.对齐网格项目和轨道

首先我们先将模块1关闭&#xff0c;模块2使用CSS网格 display: none;.container--2 {/* STARTER */font-family: sans-serif;background-color: black;font-size: 40px;margin: 100px;width: 1000px;height: 600px;/* CSS GRID */display: grid;}然后我们常间一个三列两行的网…

STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

文章目录 一、基础知识点二、开发环境三、STM32CubeMX相关配置四、Vscode代码讲解五、结果演示串口显示乱码解决方案 一、基础知识点 本实验通过stm32片内资源RTC实现实时时钟&#xff0c;通过数码管显示时间。设定闹钟&#xff0c;实现准点报时。 数码管相关知识点&#xff1…