Linux工具学习之【gdb】

news2024/12/28 18:27:50

✨个人主页: Yohifo
🎉所属专栏: Linux学习之旅
🎊每篇一句: 图片来源
🎃操作环境: CentOS 7.6 阿里云远程服务器

  • Whatever is worth doing is worth doing well.

    • 任何值得去做的事情,都值得把它做好。

    向阳而生


文章目录

  • 📘前言
  • 📘正文
    • 📖生成可调试文件
      • 📃realse 与 debug
    • 📖调试打开与关闭
      • 📃启动调试
      • 📃l 查看代码
      • 📃退出调试
    • 📖运行与断点
      • 📃r 运行程序
      • 📃b 断点操作
        • 🖋️设置断点
        • 🖋️查看断点信息
        • 🖋️编号含义
        • 🖋️取消断点
    • 📖单行与单步
      • 📃n 单行调试
      • 📃s 单步调试
    • 📖查看变量
      • 📃bt 查看调用堆栈
      • 📃p 临时查看变量
      • 📃display 常显示变量
    • 📖快速跳转
      • 📃until 指定行
      • 📃finish 函数
      • 📃c 断点
    • 📖其他命令
      • 📃disable 断点使能
      • 📃set var 设置条件
      • 📃ptype 查看变量类型
  • 📘总结


📘前言

vim 可以编写代码,gcc/g++ 可以编译代码,此时只最后一件神器,就能进行完整的开发工作,那就是通过 gdb 调试代码,毕竟谁都不敢保证自己的代码没有问题,所以就有调试器这种东西帮助我们定位问题,进而解决问题

GDB的官方吉祥物?


📘正文

现在让我们一起进入 gdb 的世界,体验纯命令行调试代码的妙处
注意: 需要提前下载好 gdb

$ sudo yum install -y gdb

📖生成可调试文件

可能有的同学一安装好 gdb 就迫不及待地开始了调试,通过 gdb 最终生成文件 进入 gdb 后,会发现什么指令都用不了,除了 q 退出 gdbr 运行程序

原因很简单:gcc/g++ 默认生成的程序为 realse 发行版,也就是说不含调试信息,所以我们首先要解决这个问题
直接打开

📃realse 与 debug

程序分为 realsedebug 两个版本,其中前者是给测试工程师找毛病的,而后者则是我们开发使用的版本,debug 内置很多调试信息,因此它能很好的进行调试

gcc/g++ 默认不会生成 debug 版的可执行程序,我们可以通过指令来搜索默认生成的程序中是否含有调试信息

$ readelf -S myfile | grep -i debug	//在默认生成的可执行程序 myfile 中查找调试信息

搜索调试信息
想要解决问题也很简单:在编译时,指定编译器生成 debug 版的程序就行了

注意:因为已经学习了 Makefile ,我们直接在文件中更改就行了

//Makefile 文件中
$ gcc test.c -o myfile -g -std=c99
//注意:其中 -g 就是指定其生成 debug 版的程序;-std=c99 是让其支持C99标准

指定生成
我们先通过 make clean 指令清理原来的解决方案,然后再通过 make myfile 指令编译程序
得到可执行程序后,用同样的方法对其进行查找
调试信息
接下来就可以愉快的进入 gdb 进行调试了

📖调试打开与关闭

首先要学习如何打开和关闭 gdb

📃启动调试

我们调试的对象是已经生成的可执行程序,并非最开始的源文件
这很好理解,因为在VS中也是先编译、再调试

通过 Makefile 的自动化任务生成 myfile 可执行程序
然后通过指令 gdb myfile 即可进入调试

$ gdb myfile	//进入 gdb 调试

进入gdb
注意: 调试的是最终生成的可执行程序;要确保生成的程序为 debug 版,不然后续无法调试

📃l 查看代码

只要进入了 gdb ,我们可以通过 l 指令随时随地查看我们的代码,且查看代码时不会干扰其他调试命令

l 命令一般是配合数字进行查看,每次只可查看十行,如 l 1 就表示从代码第一行开始查看其前后十行,按回车后可接着往下展示,直到代码展示完毕

(gdb) l 1	//从代码第一行开始查看其前后十行
(gdb) l	//默认查看代码最中间的十行内容

查看代码
注意: 经过测试发现,l 的查看策略是每次展示十行,然后想要查看的第n行位于中间,l 1 能直接能从第一行开始的原因是前面已经没有代码了,因此如果默认只输入 l 就会展示当前代码的最中间位置前后十行

📃退出调试

gdb 退出不像 vim 那样麻烦,指令 q 就表示退出 gdb 调试

(gdb) q	//退出 gdb 调试

退出调试

📖运行与断点

调试最重要的目的是帮助我们快速定位到问题,然后分析解决,此时断点就显得很重要了,如果没有断点,那只能一步步的调试,效率很低,下面就来看看如何让程序在 gdb 中跑起来及断点相关操作

📃r 运行程序

gdb 中能直接快速运行程序,假设没有断点,那么程序会直接运行出结果

(gdb) r	//运行程序

运行程序
其实此时可以直接把这个看作VS中的黑框框,r 就相当于 F5 ,在没有断点的情况下,程序会直接出结果的,而最终的结果值也会紧跟着输出

📃b 断点操作

断点在 gdb 中意为 breakpoint ,其中首字母 b 就表示断点的意思,因为是纯命令行操作,所以刚开始调试麻烦点是必然的

🖋️设置断点

指令 b 需要配合行号或函数名进行断点设置

(gdb) b 行号	//在指定行号打断点
(gdb) b 函数名	//在指定函数处打断点

打断点
注意: 纯命令打的断点不如图形化界面直观,但我们也可以通过指令查看断点信息

🖋️查看断点信息

指令 info b 可以搜索所有断点,并展示其详细信息

(info) b	//查看所有断点信息

查看断点信息

🖋️编号含义

查看断点信息时,会发现有一栏 num ,这表示每个断点的编号,因为我们不能直接对断点进行区分,于是就需要引入编号这个概念,这个概念在 gdb 很多地方都有体现

注意: 除非 gdb 关闭,否则它的编号是一直累计的,比如我们把断点1、2都删了,然后再新打一个断点,断点编号就为3

🖋️取消断点

有时候想取消断点,就可以通过 d 断点编号,取消指定断点

(gdb) d 断点编号	//由此可见断点编号的重要性

断点删除
有了断点之后,我们就可以配合 r 指令,运行至断点处
断点运行
注意: 不同于VS中的 F5r 指令要么运行至最近一个断点处,要么将程序运行完,也就是说,r 是无法实现两个断点间移动的,再次按 r 会提示是否重新运行程序

📖单行与单步

调试这个东西总得一步一步来,不然问题就不好找到了

📃n 单行调试

单行调试即逐过程调试,对应着VS中的 F10,即遇到函数不会进入,指令为 n

(gdb) n	//单行调试,不会进入函数内部

单行调试
单行:一行一行的来,每次运行完一行内容即可

📃s 单步调试

单步调试对应着VS中的 F11 ,不同于单行调试,单步调试能进入函数内部,指令为 s

(gdb) s	//单步运行,会进入函数内部

单步调试
单步:即一步一步的来,如果遇到函数,就会进入函数内部,确保程序的每一步都被执行

📖查看变量

调试过程中还有一个很重要的工作:查看变量信息,如VS中的监视窗口,假设没有监视功能,那么我们可能连变量的变化情况都无法捕捉到,庆幸的是 gdb 支持监视功能

📃bt 查看调用堆栈

程序运行时,会先为 main 函数建立栈帧,然后运行程序,如果遇到函数,就会为函数建立栈帧,执行函数,因此程序的运行本质上就是栈帧的创建与销毁

我们可以通过指令 bt 查看当前程序的堆栈调用情况

(gdb) bt	//查看调用堆栈情况

调用堆栈

📃p 临时查看变量

指令 p 变量 可以查看指定变量的信息

(gdb) p 变量	//查看变量的信息

查看变量
注意: 指令 p 只能做到临时监视,当执行下一条指令后,原来监视的变量就看不到了;可以看出,p 监视出的值也是有编号的,每调用一次指令,编号就会累加一次

📃display 常显示变量

gdb 当然也支持一直监视变量,使用指令 display 即可

(gdb) display 变量	//常显示变量信息,不会随着指令的执行而消失

常显示
注意: 如果我们忘记了程序中有哪些变量,可以随时随地通过 l 指令查看,像这种查看式的指令,是不会影响其他指令运行的;不难发现,常显示的变量也有属于自己的编号,这个编号运行机制跟断点的一样,只要 gdb 不退出,它是会一直累加的

编号存在的主要意义就是方便我们进行监视变量删除

(gdb) undisplay 变量编号	//取消监视指定变量

📖快速跳转

gdb 提供了一些快速跳转的指令,赋予了我们在不打断点的情况下进行跳转的权力(注:先要打断点将程序运行起来),这是VS做不到的

📃until 指定行

程序运行后,我们可以直接通过 until 行号 的方式跳转至指定行,这个指令通常用来跳过循环

(gdb) until 行号	//跳转至指定行

until 跳转

📃finish 函数

这个指令主要是针对函数的,直接 finish 就可以在不打断点的情况下,跑完当前函数

(gdb) finish 	//在不打断点的情况下跑完当前函数

finish 函数

📃c 断点

这个指令就是针对断点的了,前面说过 r 无法实现两个断点间的跳转,因此有一个专门的命令 c 进行断点跳转(注:依然需要先通过 r 指令把程序跑起来)

(gdb) c	//进行断点间的跳转

断点跳转

📖其他命令

接下来再列举一些其他命令

📃disable 断点使能

使能 的意思就是开关,比如电灯的开与关,我们的断点也能设置开关状态,在不取消断点的情况下让断点失效

(gdb) disable 断点编号	//关闭断点

关闭断点
能关闭当然也能打开

(gdb) enable 断点编号	//打开断点

打开断点

📃set var 设置条件

给变量设置条件,使程序运行至设定值那一步,比如 set var i=5 后,程序就运行至 i=5 的那一步了

(gdb) set var 变量值	//设置变量值

设置变量值
这个功能就像VS中的给断点设置条件,然后跳转

📃ptype 查看变量类型

查看变量类型本文只是介绍了部分常用指令,关于 gdb 还有很多很多指令,一时半会是学不完的,感兴趣的同学可以去这篇文章里看看《GDB使用详解》


📘总结

以上就是关于Linux工具:gdb 的全部介绍了,gdb 是一款功能丰富的调试器,它赋予了我们在纯命令行环境下调试代码的能力,虽然它的使用门槛高,但用熟后就会很顺手,配合我们之前学习过的 vimgcc ,能做到像VS那样的开发环境,让我们的 Linux 使用场景更加丰富

如果你觉得本文写的还不错的话,期待留下一个小小的赞👍,你的支持是我分享的最大动力!

如果本文有不足或错误的地方,随时欢迎指出,我会在第一时间改正

星辰大海

相关文章推荐
Linux工具学习之【git】(版本管理神器)
Linux工具学习之【gcc/g++】(实用的编译器)
Linux工具学习之【vim】(强大的编辑工具)
Linux 权限理解和学习(热榜文章,阅读量5k+)
听说Linux基础指令很多?这里都帮你总结好了

感谢支持

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

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

相关文章

【HTML】一款可交互的响应式登陆注册表单,你确定不来看看嘛(附源码)

💂作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后…

2022年五一杯数学建模C题火灾报警系统问题求解全过程论文及程序

2022年五一杯数学建模 C题 火灾报警系统问题 原题再现: 二十世纪90年代以来,我国火灾探测报警产业化发展非常迅猛,从事火灾探测报警产品生产的企业已超过100家,年产值达几十亿元,已经成为我国高新技术产业的一个组成…

Docker之Nginx部署前端项目

目录 创建nginx容器 nginx.conf讲解 ①所有配置必须以“;”结尾 ②nginx发布java项目 nginx发布静态vue项目 nginxtomcat实现反向代理及均衡 nginxhtml静态服务器 创建nginx容器 docker run –name mynginx -d -p 80:80 -v /data/nginx/conf/nginx.conf:/etc/nginx/ngin…

6款强烈推荐的 SD卡/内存卡数据恢复软件

SD卡/内存卡在 21 世纪的作用比以往任何时候都更加重要。众所周知,SD卡/内存卡具有高数据传输率并且是便携式设备,大多数摄影师甚至智能手机用户主要依靠它们来保存所有个人或项目照片和视频。此外,SD 卡还因其与各种设备的兼容性而广受欢迎。…

JUC并发编程学习笔记——AQS个人理解

1. AQS引出 1.1 前置知识: 线程创建的四种方式:Thread、Runnable、callable、线程池 LockSupport的使用:park()和unpark()方法 LockSupport是一个工具类, 提供了基本的线程阻塞和唤醒功能,它是创建锁和其他同步组件的…

使用 NVIDIA NeuralVDB优化大规模稀疏

使用 NVIDIA NeuralVDB优化大规模稀疏 基于 OpenVDB 过去十年的发展,NVIDIA NeuralVDB 的推出对于处理极其庞大和复杂的数据集的开发人员和研究人员来说是一个游戏规则的改变者。 NVIDIA NeuralVDB 的预发布版本为 OpenVDB 带来了 AI 和 GPU 优化,将烟雾…

【OpenCV】:OpenCV人脸识别项目杂记

项目目标: 1.图片人脸识别 2.视频人脸识别 3.ESP32Cam摄像头网页视频人脸识别 项目效果视频: ESP32Cam摄像头人脸识别OpenCV本地视频人脸识别ESP32Cam摄像头人脸检测项目基础代码内容: 一、读取图片 # 导入cv模块 import cv2 as cv# 读取图…

如何设置Excel表格以“只读模式“打开

设置Excel表格以“只读模式”打开,可以防止意外修改表格内容,因为“只读模式”下的Excel无法直接保存,这样就不用担心表格意外修改,关闭时又不小心保存了。 这个模式我们可以通过“另存为”的方法来设置。 打开Excel表格后&…

【学习笔记之Linux】工具之gcc/g++

背景知识: gcc/g是一个编译器,注意区分编译器和编辑器,vim是是编辑器。简单的说,编辑器是我们敲代码的工具,我们在编辑器上写出我们需要实现的功能;编译器负责实现功能,把我们写的高级语言编译成…

马蹄集 古人的剩余定理

古人的剩余定理 难度&#xff1a;白银 ©时间限制&#xff1a;1秒 巴占用内存&#xff1a;64M 今有物不知其数&#xff0c; 三三数之剩二&#xff0c; 五五数之剩三&#xff0c; 七七数之剩二。 问物最少几何&#xff1f; #include <bits/stdc.h> using nam…

使用Paddle飞桨重写波士顿房价预测案例

1.Paddle飞桨设计之“道” 当读者使用飞桨框架编写多个深度学习模型后&#xff0c;会发现程序呈现出“八股文”的形态。即不同的程序员、使用不同模型、解决不同任务的时候&#xff0c;他们编写的建模程序是极其相似的。虽然这些设计在某些“极客”的眼里缺乏精彩&#xff0c;…

XJar加密工具java打的包jar包加密运行,防止反编译

XJar功能特性 基于对JAR包内资源的加密以及拓展ClassLoader来构建的一套程序加密启动&#xff0c;动态解密运行的方案&#xff0c;避免源码泄露以及反编译。支持Maven插件加密过程需要Go环境&#xff1b;加密后生成Go启动器&#xff0c;保护密码不泄露GitHub: GitHub - core-l…

JSP SSM网上预约挂号系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 JSPSSM网上预约挂号系统 是一套完善的系统源码&#xff0c;对理解JSP java SrpingMVC mybiats 框架 MVC编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;以及相应配套的设计文档 &#xff0c;系统主要采用B/S模式开发。研究的基本内容…

马蹄集 非常大的N

非常大的N 难度&#xff1a;白银 时间限制&#xff1a;1秒 巴占用内存&#xff1a;64M 编写程序求11/2-21/231/2-41/251/2..N1/2。 格式 输入格式&#xff1a;输入为正整数 输出格式&#xff1a;输出为浮点型&#xff08;保留六位小数&#xff09;。 #include <bits/stdc.h…

系统排障掉坑背锅?亚马逊云科技要为开发者研发提效了

出品 | CSDN 云计算任何中大型企业里的 IT 系统&#xff0c;都会有多个业务应用、多种开发语言、技术栈并存。尤其要进入云上现代化应用开发的企业和开发者&#xff0c;将面对云原生庞杂的技术分支。开发者的苦与痛&#xff1a;非功能性研发、故障排查被甩锅然而&#xff0c;IT…

深夜修复Linux桌面无法启动

玩了很久了&#xff0c;突然想学习一下&#xff0c;想做一个KDE任务栏的网速插件。 Netspeed Widget - KDE Store GitHub - dfaust/plasma-applet-netspeed-widget: Plasma 5 widget that displays the currently used network bandwidth deepin15 注销切换到 KDE Ctrl Alt …

Idea同步失败Unresolved dependency的解决办法

下载一些开源的库&#xff0c;经常会碰到一些同步问题&#xff0c;本文就该系列问题单独开一篇文章&#xff0c;和大家缕一缕这样的问题怎么解决。文章在实践过程中会保持同步更新&#xff0c;大家可以点击收藏以便于下次遇到类似问题可以快速找到解决办法。 IDEA的同步问题多…

Dbeaver连接TDengine时序数据库

前言 还是结合上一阶段的工作&#xff0c;为TPS满足合同里的要求&#xff0c;预研数据库切换为TDengine。所以查看数据的工具我得能连上去看&#xff0c;习惯了Dbeaver&#xff0c;所以先把Dbeaver整的能连接使用。 一、Dbeaver对TDengine支持情况 这个数据库是国产开源的时序数…

温酒读Qt:QObject 序篇

一、醉言醉语话夏娃 跟Qt框架打了这么久交道&#xff0c;Qt貌似对我的半斤八两知根知底&#xff0c;我对Qt的认知却还不到半斤八两。o(╥﹏╥)o 或许你知道Qt的meta-object和属性系统&#xff0c;或许你在写代码时无数次显示或者隐示的继承了QObject&#xff0c;不管人家是否乐…

vue入门到精通(二)

6.组件间通信 组件有 分治 的特点&#xff0c;每个组件之间具有一定的独立性&#xff0c;但是在实际工作中使用组件的时候有互相之间传递数据的需求&#xff0c;此时就得考虑如何进行 组件间传值 的问题了。 完整案例:05_component/28_parent_child_component.html父子组件 &…