【Linux】Linux工具——gdb

1. gdb 概述

GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在 UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。

一般来说,GDB主要帮忙你完成下面四个方面的功能:

  • 1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
  • 2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
  • 3、当程序被停住时,可以检查此时你的程序中所发生的事。
  • 4、动态的改变你程序的执行环境。

从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。

2.使用gdb

mycode.c

 我们先生成一个Debug版本的可执行程序(gcc加上-g选项)

我们可以验证一下它是不是含有debug信息

 很好,有

接下来我们就可以使用gdb进行调试了

在此之前要确保安装了gdb

2.1.显示代码

 l(list) 行号/函数名 —— 显示对应的code,每次10行

  • 首先若是直接【L】的话便会随机显示出该源文件中的随机10行内容,这不是我们想要的
  • 若是【l 0】或者是【l 1】的话那就是从第一行开始往下列10行的内容
    • 注意这里的L是小写,而且与数字之间要有一个空格
  • 我们想要看第二行或者第10行,可以像下面这么做

  • 这个也没有显示出全部代码啊!!!只需要多Enter几次就可以了,gdb会自动记忆你上次敲入的指令

  • 我们还可以查看一个函数

2.2.设置断点

  • r或run:运行程序。

因为我们还没有设置断点,所以一直执行到尾了

 我们现在来打断点

  • break/b 行号:在某一行设置断点
  • break/b 函数名:在某个函数开头设置断点
  • b/break 源文件:行号 —— 在该源文件中的这行加上一个断点 

2.3.查看断点信息

 我们打了3个断点,我们发现我们的断点不像windows上面的断点,我们现在看不到断点,那我们怎么去查呢?

  • info break/b :查看断点信息。
  • 若是直接执行【info】的话,出来的就是所有的调试信息
  • 但若是我们只想查看一下所打的断点的信息,那就在后面加个b/break

 断点的信息都显示出来了

  • 接下来简要介绍一下断点的一些字段信息
  • Num —— 编号
  •  Type —— 类型
  •  Disp —— 状态
  •  Enb —— 是否可用
  •  Address —— 地址
  •  What —— 在此文件的哪个函数的第几行
  • 最后的话就是每个断点信息的下面这块breakpoint already hit 1 time即此断点被命中1次

2.4.删除断点 

我们想删除断点,该怎么做呢?

我们先看看我们之前设置的断点

  •  d + 当前要删除断点的编号 —— 删除一个断点【不可以d + 行号】
  • d + breakpoints —— 删除所有的断点
  • 此时若继续将这个20行的断点打上时,就可以发现其编号为【4】,而并不是从1开始,这是因为我们没有退出过gdb,所以会持续上一次的编号继续往下

2.5.开启/禁用断点

  •   disable b(breakpoints) —— 使所有断点无效【默认缺省】
  • 我们看到所有断点的Enb从y变成了n,代表从可用变成了不可用
  • enable b(breakpoints) —— 使所有断点有效【默认缺省】
  • 我们看到所有断点的Enb从n变成了y,代表从不可用变成了可用
  • disable b(breakpoint) + 编号 —— 使一个断点无效【禁用断点】

  • enable b(breakpoint) + 编号 —— 使一个断点有效【开启断点】

2.6.运行/调试 

r(run) —— F5【无断点直接运行、有断点从第一个断点处开始运行】

  • 首先若是将断点删除掉,使用【r】指令运行的话就会直接运行到程序结束
  • 再加上断点去运行的话就会在打的断点处停下来

2.7.逐过程和逐语句 

我们先看看我们设置的断点 

 n(next) —— 逐过程【相当于F10,为了查找是哪个函数出错了】

  • 可以看到,我从第一个断点处也就是17行的位置开始执行,按下【n】之后因为在其后即19行有一个断点,此时就会直接运行到断点处
  • 按n,再按n,直到结束
  • s(step) —— 逐语句【相当于F11,一次走一条代码,可进入函数,同样的库函数也会进入】

  • 此时我们按下【s】,也就相当于是【step】,让程序一步一步地走,继而进入了Addtop这个函数(如下图),若是你在printf()语句要执行时按下【s】的话gdb就会进入printf()库函数内部去执行,这里就不展示了

  • 接下去我们可以就继续【n】,然后进行逐过程调试,来到for循环中,那么逐过程也就是变量i的累加和计数器count的累加,所以会反复执行(通过图中最左侧可以看出是第8行和第10行在反复执行)
  • 可以看到后面我没有再按【n】了,但是依旧会执行上面的步骤,这点上面也有提到过,因为gdb会自动化记忆你上一次执行过的命令,所以若是不想再敲了,直接Enter就可以了

2.8.打印 / 追踪变量 

p(print) 变量名 —— 打印变量值

  • 都执行了那么多次了,不知道【i】和【count】发生了怎样的变化,将它们打印出来看看吧
  • 通过继续执行【n】,然后再去打印就可以发现i的值和count的值发生了变化
  • 但是你不觉得这样每次去打印会显得很繁琐吗,那一定会的,所以我们有更好的办法💡

    display —— 跟踪查看一个变量,每次停下来都显示它的值【变量/结构体…】
  • 我们也可以去追踪一下这两个变量的地址,不过可以看到对于地址来说是不会发生改变的
  • 但是呢,每次都追踪打印这么多内容又太多了,我想把它们取消了可以吗?答:当然是可以的
  • 既然有display那就有undisplay
  • undisplay + 变量名编号 —— 取消对先前设置的那些变量的跟踪

2.9. 查看函数调用 

bt —— 看到底层函数调用的过程【函数压栈】

  • 通过仔细观察刚才追踪的4个变量最左侧的编号,就可以看到它们的排列的顺序是倒着的。因为变量i和变量res是我们先追踪的,它们的地址是我们后追踪的,所以可以看出这很像是一个压栈的过程
  • 其实不仅是对于它们,Addtop函数和main函数也呈现这样的关系。此时我们就可以通过【bt】这个指令来查看函数压栈的过程,此时便可以看到因为

2.10.修改变量的值 

set var —— 修改变量的值

  • 对于这个修改变量的值,很像是在VS里调试之前设置的那种条件断点,可以使调试开始后直接运行到此断点处。不过对于【set var】而言是在调试过程中进行设置

 2.11.gdb指令合集

注:()括号里面是该指令的全称 

  1.  l(list) 行号/函数名 —— 显示对应的code,每次10行
  2. r(run) —— F5【无断点直接运行、有断点从第一个断点处开始运行】
  3. b(breakpoint) + 行号 —— 在那一行打断点
  4. b 源文件:函数名 —— 在该函数的第一行打上断点
  5. b 源文件:行号 —— 在该源文件中的这行加上一个断点吧
  6. info b —— 查看断点的信息
  7. breakpoint already hit 1 time【此断点被命中一次】
  8. d(delete) + 当前要删除断点的编号 —— 删除一个断点【不可以d + 行号】

  • 若当前没有跳出过gdb,则断点的编号会持续累加
  1. d + breakpoints —— 删除所有的断点
  2. disable b(breakpoints) —— 使所有断点无效【默认缺省】
  3. enable b(breakpoints) —— 使所有断点有效【默认缺省】
  4. disable b(breakpoint) + 编号 —— 使一个断点无效【禁用断点】
  5. enable b(breakpoint) + 编号 —— 使一个断点有效【开启断点】

  • 相当于VS中的空断点
  1. enable breakpount —— 使一个断点有效【开启断电】
  2. n(next) —— 逐过程【相当于F10,为了查找是哪个函数出错了】
  3. s(step) —— 逐语句【相当于F11,】
  4. bt —— 看到底层函数调用的过程【函数压栈】
  5. set var —— 修改变量的值
  6. p(print) 变量名 —— 打印变量值
  7. display —— 跟踪查看一个变量,每次停下来都显示它的值【变量/结构体…】
  8. undisplay + 变量名编号 —— 取消对先前设置的那些变量的跟踪

  • 排查问题三剑客🗡
  1. until + 行号 —— 进行指定位置跳转,执行完区间代码
  2. finish —— 在一个函数内部,执行到当前函数返回,然后停下来等待命令
  3. c(continue) —— 从一个断点处,直接运行至下一个断点处【VS下不断按F5】

3.最常用指令(指令三剑客) 

掌握了上面的这些,你就可以在Linux下调一些简单的代码了,不过想做到高效地进行调试,就需要学习一下【三剑客】

3.1.指定行号跳转 

until + 行号 —— 进行指定位置跳转,执行完区间代码

  • 可以看到,当前在for循环内容执行累加的逻辑,但若是我们一直这么执行下去,就没有时间排错了,除了上面的哪一种【set var】之外,还有一种方法其实起到直接结束当前循环的作用,那就是进行指定行号跳转
  • 通过观察下图可以看到,当我们运行了until 13之后,程序直接就给出了我们最终的结果count,而且即将要执行最后的打印语句,说明我们跳转成功了
  • 然后可以看到,在获取到返回值后,也就直接进行了printf打印

3.2.强制执行函数 

finish —— 在一个函数内部,执行到当前函数返回,然后停下来等待命令

  • 有时候我们会有这样的需求,在初步排查的时候推断可能是某个函数内部的逻辑出了问题,但是呢又不想一步步地进到函数内部进行调试,在VS中其实很简单,只需要在函数下方设个断点,然后F5直接运行到断点处即可
  • 但是在Linux下的gdb中,我们可以使用【finsh】指令来直接使一个函数执行完毕。从下图我们可以看到,首先【s】进到函数内部,接下去我直接使用finish,可以看到它直接回到了调用函数的位置,returned了一个返回值

3.3.跳转到下一断点

c(continue) —— 从一个断点处,直接运行至下一个断点处【VS下不断按F5】

  • 这点也是我刚才在上面有提到过的,在VS中,我们要直接跳转到下一个断点处只修要按下F5即可,那在gdb中该如何操作呢,你需要敲个【c】就可以了
  • 从下图我们可以看出,对于这个指令的用处可谓是非常大,当我处于第一个断点也就是20行的时候,直接敲下【c】,就可以运行到第二个断点处也就是第10行。之后若反复敲【c】,因为这是一个单语句的循环,所以循环的下一次还是会执行到此处。上面的这两个功能就和我们在VS中用的F5是一个道理

4.gdb实战演练

  •  本次演示使用的代码是
  • 我们取名mycode.c,用gcc编译成带有debug信息的
  • 接下来,我们进入GDB 调试模式。

  • 首先我们在程序第16行设置上一个断点,然后【r】从第15行开始运行
  • 然后我们使用【s】进入到swap函数中,因为我首先不想调试,想先立马看看运行结果,但是此时又已经进入调试了,那么我们就可以使用到【finish】来立马执行完这个函数,然后观察一下结果
  • 可以看到,最后打印出结果的时候a和b的值确实发生了交换
  • 既然清楚了二者会进行一个交换,接下去我们就逐语句【n】进行一个单步追踪吧
  • 因为提前看了执行结果,所以我们要重新开始调试,按下【r】即可,它会询问你是否需要重新开始调试,选择y之后就可以重新从16行开始进行调试
  • 首先通过【display】记录一下两个变量的值和地址
  • 接着按【s】进入到swap函数里,追踪一下指针x和指针y的内容,也就是它们所存放的地址,就可以看到,函数内部已经接受到了这两个变量的地址
  • 然后对我们要观察的值变化继续做一个追踪
  • 并且在执行完第一个语句t = *x时,临时变量t中已经存放了变量a的值,也就是指针所指向的那块空间中的值
  • 接下去执行*x = *y,此时*x中的值就发生了变化,因为指针x可以直接找到变量a的地址,所以可以对其中的内容做修改,就变为了20
  • 接下去执行*y = t,同理,指针y可以直接找到变量b的地址,所以可以对其中的内容做修改,将原本保存在临时变量t中的10赋值给到*y,也就修改了其中的内容
  • 再按【n】的话这个swap函数就执行结束了,回到了main函数,就可以清楚地看到函数内部的修改带动了函数外部值的变化,真正地通过【传址调用】交换了两个数
  • 整体的调试结束!!!!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记忆化搜索汇总

记忆化搜索简介 记忆化搜索(Memoization Search):是一种通过存储已经遍历过的状态信息,从而避免对同一状态重复遍历的搜索算法。 记忆化搜索是动态规划的一种实现方式。在记忆化搜索中,当算法需要计算某个子问题的结果…

面试题------>MySQL!!!

一、连接查询 ①:左连接left join (小表在左,大表在右) ②:右连接right join(小表在右,大表在左) 二、聚合函数 SQL 中提供的聚合函数可以用来统计、求和、求最值等等 COUNT&…

Docker配置 之 本地仓库web访问

介绍 Docker是一种开源的应用容器引擎。 Docker可以让开发者打包应用以及依赖包到一个可移植的容器中,然后发布到任何安装了Docker引擎的服务器上(包括Linux机器、Windows机器),也可以实现虚拟化。容器是完全使用沙箱机制&#…

【javaEE初阶】

🌈🌈🌈关于java ⚡⚡⚡java的由来 我们这篇文章主要是来介绍javaEE,一般称为java企业版,实际上java的历史可以追溯到上个世纪90年代,当时主要的语言主流的还是C语言和C,但是在那个时期嵌入式初…

js 一维数组转多维数组

效果图: //源数组const arrList [{"id": 1,"code": "001","name": "第一个","parentCode": "",},{"id": 2,"code": "00101","name": "第一…

使用gradio库实现Web应用,允许用户上传图像,并使用YOLOv8模型对图像进行目标检测。

一、Gradio Gradio 详细介绍 Gradio 是一个用于构建和分享机器学习模型和数据科学应用的开源Python库。它简化了创建交互式Web界面的过程,让开发者可以快速搭建原型并与他人分享。 主要特性 易用性: 无需前端开发经验:只需几行Python代码就…

【简单理解化】 内存函数及它的模拟实现

本文章谈论memcpy,memcmp,memmove,memset函数 目录 1.memcpy的使用和模拟实现 2.memmove的使用和模拟实现 3.memset的使用 4.memcmp函数的使用 1.memcpy的使用和模拟实现 该函数用于从源内存块复制指定数量的字节到目标内存块 1 void * memcpy ( void * destination, const voi…

DVWA-CSRF

CSRF Low 观察后端代码,只要password_new等于password_conf就可以修改密码。由于这两个参数是通过GET传递的,所以直接构造payload。 http://192.168.20.156/DVWA/vulnerabilities/csrf/?password_newpass&password_confpass&ChangeChange# 这…

Windows开启远程桌面

搜索并进入【远程桌面设置】 ​​ 开启远程桌面 ​​​ ipconfig​命令查看ip地址,并使用地址在另一台电脑远程登录此电脑 选择其他账户登录,输入用户和密码 ​​ ​​ 成功登录 ​​

判断经纬度是否在某个城市内

一、从高德获取指定城市边界经纬度信息 通过apifox操作&#xff1a; 二、引入第三方jar包&#xff1a; maven地址&#xff1a;https://mvnrepository.com/ maven依赖&#xff1a; <dependency><groupId>org.locationtech.jts</groupId><artifactId>…

Spring Boot整合Jasypt 库实现配置文件和数据库字段敏感数据的加解密

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

【全开源】Shopro社区团购(小程序版)

邻里间的购物新选择 基于Fastadmin后端管理系统Uniapp客户端&#xff08;仅支持微信小程序&#xff09;开发&#xff0c;生鲜果蔬社区团购的不二之选、快速搭建社区团购平台、让你的产品走进上千个社区。线上团购线下自提&#xff0c;玩转社区消费新模式提供专业、优质的社区团…

如何解决chatgpt出现503 bad gateway的问题

昨日&#xff0c;ChatGPT官网挂了&#xff0c;也就是使用web网页端访问的用户&#xff0c;会出现 bad gateway 情况。我们去ChatGPT官方的监控查看&#xff0c;已经展示相关错误。 影响的范围有&#xff1a; 影响了 ChatGPT 所有计划的所有用户。影响包括所有与 ChatGPT 相关…

实验四、零比特插入《计算机网络》

但凡这句话有一点用的话也不至于一点用都没有。 目录 一、实验目的 二、实验内容 三、实验小结 一、实验目的 掌握零比特插入原理及方法使用任意编程语言实现零比特插入方法。 二、实验内容 掌握零比特插入原理及方法 点对点协议 PPP&#xff08;Point-to-Point Protoco…

计算机三级等级考试

计算机等级考试&#xff1a; 一&#xff1a;理论知识考试 100分考60分 1&#xff1a;题库 二&#xff1a;技能考试 100分考60分 1&#xff1a;写文档 项目概述 功能描述 数据库设计 UML 绘 图 用例图 与 包图&#xff08;两个图&#xff09; 2&…

网络运维简介

目录 1.网络运维的定义 2.诞生背景 3.网络运维的重要性 4.优点 5.缺点 6.应用场景 6.1.十个应用场景 6.2.数据中心运维 7.应用实例 8.小结 1.网络运维的定义 网络运维&#xff08;Network Operations&#xff09;是指管理、监控和维护计算机网络以确保其高效、安全和…

校园安保巡逻机器人

2023年8月5日&#xff0c;陕西西安一高校实验室起火冒烟&#xff0c;导致学校化学实验室发生火灾。2022年8月3日&#xff0c;一名歹徒持械闯入江西吉安安福县城的一家私立幼儿园&#xff0c;对着无辜的幼儿行凶伤人&#xff0c;造成3死6伤。 像这样的事故有不断地发生&#xf…

2024首发!会声会影2024旗舰版,专业编辑新体验!

会声会影2024最新旗舰版是一款专业的视频编辑软件&#xff0c;它集成了多种高级功能&#xff0c;为用户带来极致的视频编辑体验。在这篇文章中&#xff0c;我们将详细介绍该软件的功能和特色&#xff0c;帮助用户更好地了解和使用它。 会声会影全版本绿色安装包获取链接&#…

【云岚家政】-day00-开发环境配置

文章目录 1 开发工具版本2 IDEA环境配置2.1 编码配置2.2 自动导包设置2.3 提示忽略大小写2.4 设置 Java 编译级别 3 Maven环境3.1 安装Maven3.2 配置仓库3.3 IDEA中配置maven 4 配置虚拟机4.1 导入虚拟机4.2 问题 5 配置数据库环境5.1 启动mysql容器5.2 使用MySQL客户端连接数据…

【Python数据类型的奥秘】:构建程序基石,驾驭信息之海

文章目录 &#x1f680;Python数据类型&#x1f308;1. 基本概念⭐2. 转化&#x1f44a;3. 数值运算&#x1f4a5;4. 数值运算扩展(math库常用函数) &#x1f680;Python数据类型 &#x1f308;1. 基本概念 整数&#xff08;int&#xff09;&#xff1a;整数是没有小数部分的数…