【Linux系统】—— 调试器 gdb/cgdb的使用
【Linux系统】—— 调试器 gdb/cgdb的使用
- 1 前置准备
- 2 快速认识 gdb
- 3 cgdb/gdb 的使用
- 3.1 简单认识 cgdb
- 3.2 打断点 / 删断点
- 3.3 逐过程 / 逐语句
- 3.4 查看变量
- 3.5 快速跳转
- 4 cgdb/gdb 调试技巧
- 4.1 watch
- 4.2 「set var」确定问题原因
- 4.3 条件断点
- 5 概念理解
- 6 gdb/cgdb 指令一览
1 前置准备
程序的发布方式有两种, debug 模式和 release 模式, Linux gcc/g++ 出来的⼆进制程序,默认是 release 模式。
程序要调试,必须是debug模式
要使用 gdb 调试,必须在使用 gcc/g++ 源代码⽣成⼆进制程序的时候,加上 「-g」 选项,如果没有添加,程序无法被编译
- 「-g」选项:让最后形成的可执行程序,添加调试信息 —— d e b u g debug debug 模式
$ gcc mycmd.c -o mycmd # 默认模式,不⽀持调试
$ file mycmd
mycmd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-px86-64.so.2,
BuildID[sha1]=82f5cbaada10a9987d9f325384861a88d278b160, for GNU/Linux
3.2.0, not stripped$ gcc mycmd.c -o mycmd -g # debug模式
$ file mycmd
mycmd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-x86-64.so.2,
BuildID[sha1]=3d5a2317809ef86c7827e9199cfefa622e3c187f, for GNU/Linux
3.2.0, with debug_info, not stripped
样例代码:
#include <stdio.h>int Sum(int s, int e)
{int result = 0;for(int i = s; i <= e; i++){ result += i;} return result;
} int main()
{int start = 1;int end = 100;printf("I will begin\n");int n = Sum(start, end);printf("running done, result is: [%d-%d]=%d\n", start, end, n); return 0;
}
2 快速认识 gdb
g d b gdb gdb下载:
- sudo apt install -y gdb / sudo yum install -y gdb
进入调试:
gdb 可执行文件
退出调试:
q(quit)
常见选项:
「-q」:安静模式,不打印介绍信息和版本信息
查看源码:
l(list): 查看源程序代码,默认显示 10 行,按回车键继续看余下的。 后面可以跟文件名表明要看的指定文件,默认当前文件l(list) 【指定文件】
注:l(list)后面加行号,查看指定行号的前后十行
3 cgdb/gdb 的使用
3.1 简单认识 cgdb
看了 g d b gdb gdb 的基础操作,许多小伙伴都会认为 g d b gdb gdb 难用。也难怪,我调试的时候连看个源代码都那么麻烦,我还怎么调试。
为了解决 g d b gdb gdb 难用的问题,可以使用 cgdb 进行调试
c g d b cgdb cgdb 和 g d b gdb gdb 的命令是一模一样的,但 c g d b cgdb cgdb 可以给我们动态呈现我们的代码
cgdb下载指令:
- Ubuntu: sudo apt-get install -y cgdb
- Centos: sudo yum install -y cgdb
cgdb 界面:
3.2 打断点 / 删断点
开始调试(相当于VS:F5):
r(run):程序开始运行,遇到断点停止否则运行至结束
程序运行中可以再次按:「r」,从新开始调试( gdb 会出现提示,按 y 即可)
设置断点(相当于VS:F9):
b(break):在某行设置断点 使用指令: b [行号] / b [指定文件:] [行号] / b [指定文件:][指定函数名]
注:给函数名打断点实际上是给函数的第一句指令打断点
查看断点:
- 使用指令:
info b
显示断点信息对应的含义:
- Num:断点编号
- Disp:断点执行一次之后是否有效 keep:有效 dis:无效
- Enb: 当前断点是否有效 y:有效 n:无效
- Address:断点内存地址
- What:位置
删除断点:
- 使用指令:
d(delete) 断点编号
注:删除断点只能根据断点编号删除,不能根据行号删除
2 号断点被删除后,3 号断点的编号并没有变成 2 号,新增的断点也是从 4 号开始。所以断点编号不会被修改,依次线性递增,除非退出再进入 gdb / cgdb。
禁用断点:
断点是可以被使能的,即用的时候打开,不用的使用关闭(不是删除)
为什么要禁用断点呢?我既然不用了,直接删掉它不就行了吗。每个断点打的位置都是有讲究,可能这次调试你不需要用这断点,便把断点删掉了,但下次再调试就不知道之前这个断点打在哪里了。
正确的做法是将断点使能(使之能或使之不能),这样的断点的痕迹还在,就能找到历史的调试痕迹
使用指令:
disable 断点编号
注:只有打断点是行号,其他对断点的操作都是断点编号
打开断点:
- 使用指令:
enable 断点编号
3.3 逐过程 / 逐语句
逐过程(相当于VS:F10)
- 使用指令:
n(next)
逐语句(相当于VS:F11)
- 使用指令:
s(step)
注:gdb / cgdb 会自动记录最新的指令,按 “回车” 可以自动执行最新的指令
3.4 查看变量
临时查看变量值
- 使用指令:
p 变量名
常久显示变量值(相当于VS的监视窗口)
- 使用指令:
display 变量名
删除显示的变量名
- 使用指令:
undisplay 常显示的编号
查看当前函数定义的所以临时变量
- 使用指令:
info locals
调用栈帧:
- 使用指令:
bt
Sum的函数栈帧 递归类的程序我们就可以用
bt来看其调用栈
3.5 快速跳转
运行至下一个断点处(相当于VS:F5)
- 使用指令:
c(continue)
直接执行到当前函数返回处,然后停止
- 使用指令:
finish
跳出当前循环
- 使用指令:
until 行号
until可以用来跳转至指定行,常用来跳出当前确定没出错的循环。严格意义上不是跳转,而是将循环当前循环跑完了
4 cgdb/gdb 调试技巧
4.1 watch
「watch」可以用来监视变量或者某个表达式的变化,如果监视的表达式在程序运行期间的值发⽣变化,gdb会通知使用者
删除「watch」和删除断点一样,使用「d」指令
「watch」有什么用呢?
最主要的用途是:如果你有⼀些变量不应该修改,但是你怀疑它修改导致了问题,你可以「watch」它,如果变化了,就会通知你
4.2 「set var」确定问题原因
我们故意写个错误代码:我们设置一个标志位 flag,为 1 得到正数 result;-1 得到负的 result,但现在粗心的将 flag 的值设为 0
进入 gdb 利用「set var」调试
所以我们可以用「set var」确定并更改我们出错的原因
4.3 条件断点
int Sum(int s, int e)
{int result = 0;for(int i = s; i <= e; i++){ result += i;} return result * flag;
}
上述函数,如果我们想直接看 i = 10 时的各变量值怎么办,即跳过部分循环。
在VS调试中,我们往往是,添加语句 if(i == 10),并在该语句打断点
int Sum(int s, int e)
{int result = 0;for(int i = s; i <= e; i++){ if(i == 10)printf("hehe"); //添加语句,并将断点打在该语句上result += i;} return result * flag;
}
在 gdb 的调试中,我们可以用
条件判断来做到
- 使用指令:
b 行号 if 条件
例如:result += i;语句在第12行
删除条件断点的方法同样是用命令:「d」
给已经存在的断点设置条件
- 使用指令:
condition 断点编号 条件(注:没有if)
5 概念理解
调试的本质是什么?
调试的本质是帮我们解决问题吗?我们仔细想一想,好像 VS 的调试器、gdb/cgdb 等工具并没有帮我们解决,它们仅仅是给程序员追踪内存、查看变量等,真正去解决问题的还是我们自己。
所以调试的第一件事情就是先找到问题。调试器就是帮我们找到问题的,找到问题后,我们要查看问题代码的上下文做排除,最后才能解决问题。解决问题并不是调试器帮我们解决问题,是我们自己解决问题。
所以,我们用调试器调试时,最核心的就是用调试器找到问题。
gdb 有很多命令是帮我们找到问题的,最核心的就是:
c:通过断点进行分块,以块为单位快速定位区域finish:确认问题是否在当前函数内until:局部区域快速执行
如何快速找到问题所在呢?
比如现在有 100 行代码,我们可以分别在第 25 行、50 行、75 行打上断点,这样我们就利用断点完成了代码的分块。让程序直接运行到各个断点处,就能知道是哪一块代码出现问题了。
在工程项目中,往往几十上百万行代码,又如何利用断点快速找到问题的根源呢?
我们可以现在项目的中间处打个断点,看问题出现那个部分;再在出问题部分的中间打个断点……以此类推,用二分查找的方式快速找到问题所在
断点的本质是什么?
断点的本质是对代码进行切块,以块为单位快速定位问题区
6 gdb/cgdb 指令一览
| 命令 | 作用 | 样例 |
|---|---|---|
| list/l | 显示源代码,从上次位置开始,每次列出10行 | list / l 10 |
| list/l 函数名 | 列出指定函数的源代码 | list / l main |
| list / l 文件名:行号 | 列出制定文件的源代码 | list / l mycode.c:1 |
| r / run | 从程序开始连续执行 | run / r |
| n / next | 单步执行,不进入函数内部 | n / next |
| s / step | 单步执行,进入函数内部 | s/ step |
| break / b [文件名:]行号 | 在指定行号设置断点 | break 10 / break test.c : 10 |
| break / b 函数名 | 在函数开头设置断点 | break main |
| info break / b | 查看当前所有断点的信息 | info break / b |
| finish | 执行到当前函数返回,然后停止 | finish |
| print / p 表达式 | 打印表达式的值 | print start+end |
| p 变量 | 打印制定变量的值 | p x |
| set var 变量 = 值 | 修改变量的值 | set var i = 10 |
| continue / c | 从当前位置开始连续执行程序 | continue |
| delete / d breakpoints | 删除所有断点 | delete breakpoints |
| delete / d n | 删除序号为 n 的断点 | delete / d 1 |
| disable breakpoints | 禁用所有断点 | disable breakpoints |
| enable breakpoints | 启用所有断点 | enable breakpoints |
| info / i breakpoints | 查看当前设置的断点列表 | indo breakpoints |
| display 变量名 | 跟踪显示制定变量的值(每次停止时) | display x |
| undisplay 编号 | 取消对指定变量的跟踪显示 | undisplay 1 |
| until 行号 | 执行到指定行号 | until 20 |
| backtrace / bt | 查看当前执行栈的各级函数调用及参数 | backtrace / bt |
| info/i locals | 查看当前栈帧局部变量值 | info locals |
| quit | 退出gdb调试器 | quit |
好啦,本期关于调试器 gdb/cgdb的使用就介绍到这里啦,希望本期博客能对你有所帮助。同时,如果有错误的地方请多多指正,让我们在 Linux 的学习路上一起进步!
相关文章:
【Linux系统】—— 调试器 gdb/cgdb的使用
【Linux系统】—— 调试器 gdb/cgdb的使用 1 前置准备2 快速认识 gdb3 cgdb/gdb 的使用3.1 简单认识 cgdb3.2 打断点 / 删断点3.3 逐过程 / 逐语句3.4 查看变量3.5 快速跳转 4 cgdb/gdb 调试技巧4.1 watch4.2 「set var」确定问题原因4.3 条件断点 5 概念理解6 gdb/cgdb 指令一…...
Vue 3 中,Pinia 和 Vuex 的主要区别
总结对比表 对比项VuexPiniaAPI 设计区分 mutations/actions仅 state/actions/getters模块化嵌套式配置独立 Store,按需组合TypeScript需手动声明类型原生自动推断代码简洁性冗余(需 commit/dispatch)直接调用方法推荐场景Vue 2 升级项目/严…...
Wireshark 输出 数据包列表本身的值
在 Wireshark 中,如果你想输出数据包列表本身的值(例如,将数据包的摘要信息、时间戳、源地址、目的地址等导出为文本格式),可以使用 导出为纯文本文件 的功能。以下是详细步骤: 步骤 1:打开 Wir…...
docker部署单机版doris,完整无坑
文章目录 一、部署1、修改内核参数2、下载Docker 开发环境镜像3、下载安装包4、启动镜像5、配置fe6、配置be7、远程连接 二、运维命令参考资料 一、部署 1、修改内核参数 在启动doris的be时,需要将 Linux 操作系统的内核参数设置为2000000,这里是Doris…...
SQL注入(SQL Injection)详解与实战
文章目录 一、什么是SQL注入?二、常见SQL注入类型三、手动注入步骤(以CTF题目为例)四、CTF实战技巧五、自动化工具:SQLMap六、防御措施七、CTF例题八、资源推荐 一、什么是SQL注入? SQL注入是一种通过用户输入构造恶意…...
STM32 低功耗模式
目录 背景 低功耗模式 睡眠模式 进入睡眠模式 退出睡眠模式 停止模式 进入停止模式 退出停止模式 待机模式 进入待机模式 退出待机模式 程序 睡眠模式 休眠模式配置 进入休眠模式 退出睡眠模式 停止模式 停止模式配置 进入停止模式 退出停止模式 待机模式…...
网络安全架构战略 网络安全体系结构
本节书摘来自异步社区《网络安全体系结构》一书中的第1章,第1.4节,作者【美】Sean Convery 1.4 一切皆为目标 网络安全体系结构 当前的大型网络存在着惊人的相互依赖性,作为一名网络安全设计师,对这一点必须心知肚明。Internet就…...
【算法】回溯算法
回溯算法 什么是回溯 人生无时不在选择。在选择的路口,你该如何抉择 ..... 回溯: 是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标&am…...
AI大模型(如GPT、BERT等)可以通过自然语言处理(NLP)和机器学习技术,显著提升测试效率
在软件测试中,AI大模型(如GPT、BERT等)可以通过自然语言处理(NLP)和机器学习技术,显著提升测试效率。以下是几个具体的应用场景及对应的代码实现示例: 1. 自动生成测试用例 AI大模型可以根据需求文档或用户故事自动生成测试用例。 代码示例(使用 OpenAI GPT API): …...
Centos安装php-8.0.24.tar
查看系统环境 cat /etc/redhat-release 预先安装必要的依赖 yum install -y \ wget \ gcc \ gcc-c \ autoconf \ automake \ libtool \ make \ libxml2 \ libxml2-devel \ openssl \ openssl-devel \ sqlite-devel yum update 1、下载解压 cd /data/ wget https:/…...
机器学习(李宏毅)——RNN
一、前言 本文章作为学习2023年《李宏毅机器学习课程》的笔记,感谢台湾大学李宏毅教授的课程,respect!!! 二、大纲 引例RNN历史基本思想RNN变形RNN训练 三、引例 学习RNN之前先看一个例子: 假设要做一…...
Linux 文件系统inode软硬链接
目录 一、理解文件系统 1、前言 2、磁盘 二、inode 1、创建一个新文件的 4 个操作 三、软硬链接 1、软链接 2、硬链接 3、硬链接的应用 4、软链接的应用 一、理解文件系统 1、前言 在我们电脑文件里,分为打开的文件和未打开的文件,我们在上…...
多目标粒子群优化算法-MOPSO-(机器人路径规划/多目标信号处理(图像/音频))
具体完整算法请跳转:多目标粒子群优化算法-MOPSO-(机器人路径规划/多目标信号处理(图像/音频)) 多目标粒子群优化算法(Multi-Objective Particle Swarm Optimization,MOPSO)是一种基…...
Unity合批处理优化内存序列帧播放动画
Unity合批处理序列帧优化内存 介绍图片导入到Unity中的处理Unity中图片设置处理Unity中图片裁剪 创建序列帧动画总结 介绍 这里是针对Unity序列帧动画的优化内容,将多个图片合批处理然后为了降低Unity的内存占用,但是相对的质量也会稍微降低。可自行进行…...
LayUi点击查看图片组件layer.photos()用法(图片放大预览后滚动鼠标缩放、底部显示自定义标题)
LayUi官方文档更新后发现图片查看组件layer.photos()没有了 记录一下用法 例: <ul id""><li title"" ng-repeat"(val,item) in Obj" ng-click"gszzxxClick(item)"><img ng-src"{{item.src}}" a…...
DAY07 Collection、Iterator、泛型、数据结构
学习目标 能够说出集合与数组的区别数组:1.是引用数据类型的一种2.可以存储多个元素3.数组的长度是固定的 int[] arr1 new int[10]; int[] arr2 {1,2,3};4.数组即可以存储基本类型的数据,又可以存储引用数据类型的数据int[],double[],String[],Student[]集合:1.是引用数据类…...
k8s集群如何赋权普通用户仅管理指定命名空间资源
文章目录 1. 普通用户2. 创建私钥3. 创建 CertificateSigningRequest4. 批准 CertificateSigningRequest5. 创建 kubeconfig6. 创建角色和角色绑定7. 测试 1. 普通用户 创建用户demo useradd demo2. 创建私钥 下面的脚本展示了如何生成 PKI 私钥和 CSR。 设置 CSR 的 CN 和 …...
DeepSeek与ChatGPT的全面对比
在人工智能(AI)领域,生成式预训练模型(GPT)已成为推动技术革新的核心力量。OpenAI的ChatGPT自发布以来,凭借其卓越的自然语言处理能力,迅速占据市场主导地位。然而,近期中国AI初创公…...
C# dynamic 关键字 使用详解
总目录 前言 dynamic 是 C# 4.0 引入的关键字,用于声明动态类型,允许在运行时解析类型和成员,而非编译时。它主要设计用于简化与动态语言(如 Python、JavaScript)的交互、处理未知结构的数据(如 JSON、XML…...
sql server 数据库 锁教程及锁操作
SQL Server数据库 锁的教程 SQL Server 的数据库锁是为了保证数据库的并发性和数据一致性而设计的。锁机制能够确保多个事务不会同时修改同一数据,从而避免数据冲突和不一致的发生。理解 SQL Server 的锁机制对于开发高效、并发性强的数据库应用非常重要。 1. 锁的…...
超全Deepseek资料包,deepseek下载安装部署提示词及本地部署指南介绍
该资料包涵盖了DeepSeek模型的下载、安装、部署以及本地运行的详细指南,适合希望在本地环境中高效运行DeepSeek模型的用户。资料包不仅包括基础的安装步骤,还提供了68G多套独立部署视频教程教程,针对不同硬件配置的模型选择建议,以…...
DeepSeek24小时写作机器人,持续创作高质量文案
内容创作已成为企业、自媒体和创作者的核心竞争力。面对海量的内容需求,人工创作效率低、成本高、质量参差不齐等问题日益凸显。如何在有限时间内产出高质量内容?DeepSeek写作机器人,一款24小时持续创作的智能工具,为企业和个人提…...
用deepseek学大模型08-卷积神经网络(CNN)
yuanbao.tencent.com 从入门到精通卷积神经网络(CNN),着重介绍的目标函数,损失函数,梯度下降 标量和矩阵形式的数学推导,pytorch真实能跑的代码案例以及模型,数据,预测结果的可视化展示, 模型应用场景和优缺点…...
玩客云 IP查找
1.玩客云使用静态IP在不同网段路由器下不能使用,动态不好找IP地址 1.1使用python3 实现自动获取发送 import requests import os import socket# 从环境变量获取 PushPlus 的 token 和群组编码 PUSH_PLUS_TOKEN os.getenv("PUSH_PLUS_TOKEN") PUSH_PLU…...
【鸿蒙Next】鸿蒙应用发布前的准备
图标生成: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-apply-generated-icon-V5 debug 与 release使用不同的bundle name 鸿蒙多环境配置 https://segmentfault.com/a/1190000045418731...
【OpenCV】入门教学
🏠大家好,我是Yui_💬 🍑如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀 🚀如有不懂,可以随时向我提问,我会全力讲解~ ὒ…...
嵌入式 lwip http server makefsdata
背景: 基于君正X2000 MCU Freertoslwip架构 实现HTTP server服务,MCU作为HTTP服务器通过网口进行数据包的传输,提供网页服务。其中设计到LWIP提供的工具makefsdata,常用于将文件或目录结构转换为适合嵌入到固件中的二进制格式。 …...
qemu-kvm源码解析-cpu虚拟化
背景 Qemu 虚拟化中,CPU,内存,中断是虚拟化的核心板块。本章主要对CPU虚拟化源码进行分析 而随着技术的发展包括CPU、内存、网卡等常见外设。硬件层面的虚拟化现在已经是云计算的标配。形成了,qemu作为cpu外层控制面,…...
【蓝桥杯集训·每日一题2025】 AcWing 6123. 哞叫时间 python
6123. 哞叫时间 Week 1 2月18日 农夫约翰正在试图向埃尔茜描述他最喜欢的 USACO 竞赛,但她很难理解为什么他这么喜欢它。 他说「竞赛中我最喜欢的部分是贝茜说 『现在是哞哞时间』并在整个竞赛中一直哞哞叫」。 埃尔茜仍然不理解,所以农夫约翰将竞赛以…...
数据治理中 大数据处理一般都遵循哪些原则
在数据治理中,大数据处理通常遵循以下原则: 最小化原则:企业应只收集实现特定目的所需的数据,避免数据冗余和安全风险。 合法性原则:企业必须遵守相关法律法规,确保数据处理符合法律要求,降低法…...























