0

0

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序

星夢妙者

星夢妙者

发布时间:2025-07-04 09:00:56

|

243人浏览过

|

来源于php中文网

原创

?一、 Linux调试器 - gdb✨1. gdb是什么

gdb 是 gnu 项目开发的一个命令行源代码级调试器。它是 #%#$#%@%@%$#%$#%#%#$%@_e206a54e97690c++e50cc872dd70ee896 和其他类 unix 系统(如 macos,bsd)上 c、c++、rust、go、fortran 等编程语言开发的标准调试工具。简单来说,gdb 允许你深入正在运行的程序内部:

1️⃣启动程序: 在受控环境下运行你的程序。2️⃣暂停执行: 在特定点(断点)或发生特定事件(如信号)时停止程序。3️⃣检查状态: 当程序暂停时,你可以查看: 变量的值(局部变量、全局变量)。 程序执行到了哪一行源代码。 函数调用堆栈(backtrace)。 寄存器的内容。 内存区域的内容。4️⃣控制执行: 在暂停点之后,你可以: 单步执行代码(逐行 step 或逐过程 next)。 继续执行直到下一个断点或程序结束 continue。 跳入函数调用 step 或跳过函数调用 next。 跳出当前函数 finish。 甚至在运行时修改变量的值(小心使用!)。5️⃣分析崩溃: 当程序崩溃(如段错误 Segmentation Fault)时,GDB 可以加载产生的 core dump 文件,让你查看程序崩溃时的状态(调用栈、变量值等),极大地方便了事后分析。

总结的说就是和VS环境中进行调试是一样的效果,只不过操作不同罢了

✨2. gdb的使用更改发行版本:

默认情况下我们在Linux上是无法进行调试的,因为gcc/g++默认生成的可执行是release版本的

那么如何更改Linux下的发行版本?

gcc test.c -o testdebug -g

只需在gcc编译时后面加入-g即可

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序

使用指令

readelf -S XXXX(可执行文件名称)

就可以查看Linux下可执行程序二进制代码的一些信息。elf就是Linux下的可执行文件格式形式,可以观察到,debug版本里面多了一些调试信息

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
调试阶段:

我们将以下述代码为例进行调试:

代码语言:javascript代码运行次数:0运行复制
  1 #include  2   3   4 int Add(int left, int right)  5 {  6     return left + right;  7 }  8   9 int main() 10 { 11     int sum = Add(10, 20); 12     printf("sum = %d\n", sum);                                                                                                                            13     printf("hello gdba\n"); 14     printf("hello gdbb\n"); 15     printf("hello gdbc\n"); 16     printf("hello gdbd\n"); 17     printf("hello gdbe\n"); 18     printf("hello gdbf\n"); 19     printf("hello gdbg\n"); 20     printf("hello gdbh\n"); 21     printf("hello gdbi\n"); 22     printf("hello gdbj\n"); 23     return 0; 24 }
1️⃣进入调试模式使用指令gdb XXX(调试版本可执行)

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
2️⃣显示代码指令:l l + n(行号):从第n行开始显示

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
3️⃣断点相关指令break 行号:在某一行设置断点。b 行号即可break 函数名:在某个函数开头设置断点 info break :查看断点信息。info b即可delete 断电的编号:删除断点。d 编号即可

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
4️⃣调试运行 r:运行,有断点会在第一个断点处停下,无断点直接运行结束c:运行至下一个断点处结束

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
n:逐过程,即在调用函数处不进入函数内部s:逐语句,在调用函数处进入函数内

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
5️⃣显示变量breaktrace(或bt):查看各级函数调用堆栈p 变量:打印变量值。(该指令只会显示一次,不会随着程序的执行而变动)display 变量:常显示变量,会类似VS环境中随着程序的变动而改变undisplay 变量编号:将常显示变量取消

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
6️⃣其它指令finish:执行到当前函数返回,然后停下来等待命令(这个指令可以让我们去判断错误具体出现在那个函数)until:跳转到指定行,并且前面程序均已执行

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
7️⃣退出调试模式指令 quit:退出gdb。q即可

总结:

上面的指令都了解的话,用起来gdb已经没啥大问题了,下面把常见的一些gdb指令总结一下,如果再后续的使用过程中用到了,大家回来查阅即可。

MCP Market
MCP Market

MCP Servers集合平台,帮你找到最好的MCP服务器

下载
list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。list/l 函数名:列出某个函数的源代码。r或run:运行程序。n 或 next:单条执行。s或step:进入函数调用break(b) 行号:在某一行设置断点break 函数名:在某个函数开头设置断点info break :查看断点信息。finish:执行到当前函数返回,然后挺下来等待命令print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数 p 变量:打印变量值。set var:修改变量的值continue(或c):从当前位置开始连续而非单步执行程序run(或r):从开始连续而非单步执行程序delete breakpoints:删除所有断点delete breakpoints n:删除序号为n的断点disable breakpoints:禁用断点enable breakpoints:启用断点info(或i) breakpoints:参看当前设置了哪些断点display 变量名:跟踪查看一个变量,每次停下来都显示它的值undisplay:取消对先前设置的那些变量的跟踪until X行号:跳至X行breaktrace(或bt):查看各级函数调用及参数info(i) locals:查看当前栈帧局部变量的值quit:退出gdb?二、Linux下第一条程序-进度条✨1. 背景知识:

先看一段代码:

代码语言:javascript代码运行次数:0运行复制
#include#includeint main(){    printf("这是一个试验程序");    sleep(3);                                                                                                                                                return 0;}

运行之后,会发现,printf竟然没有打印,而是停了3秒之后才出现,相信你会说,你自己sleep了3秒,能怪人家不出现?请看下述代码:

代码语言:javascript代码运行次数:0运行复制
printf("这是一个试验程序\n"); 

如果在printf加了回车换行,你会惊奇的发现,printf先打印,然后休眠了3秒之后代码才结束,这是为何?好,知识点来了。

知识点1:

首先针对于没有回车换行,为什么没有?

是因为此时printf所要打印的内容,储存在了缓冲区,而有了\n为什么就有了呢?

这涉及到了标准输出(stdout)的缓冲机制,如下:

缓冲机制类型

行缓冲(Line-buffered):遇到换行符 \n 时自动刷新缓冲区(立即输出内容)。 全缓冲(Fully-buffered):缓冲区满或显式刷新时才输出。 无缓冲(Unbuffered):立即输出(如 stderr)。

而终端环境下的 stdout 默认是行缓冲

因此两段代码的具体解释如下:

代码语言:javascript代码运行次数:0运行复制
printf("这是一个试验程序\n");  // 末尾有换行符sleep(3);
\n 触发刷新:换行符使缓冲区立即刷新,内容立刻显示在终端。 后续休眠:之后程序休眠 3 秒,用户先看到输出,再等待。 代码语言:javascript代码运行次数:0运行复制
printf("这是一个试验程序");  // 无换行符sleep(3);
缓冲区未刷新:输出内容暂存于内存缓冲区(未满且未遇到 \n)。 先休眠 3 秒:程序进入休眠,此时终端无输出。 程序结束时刷新:main 函数返回前,自动刷新所有缓冲区,内容在休眠结束后显示。

所以也就是说终端环境下stdout是行缓冲,\n有刷新行缓冲区的功效,是!怎么证明?如下:

代码语言:javascript代码运行次数:0运行复制
int main(){    printf("这是一个试验程序");    fflush(stdout);                                                                                                                                          sleep(3);                                                                                                                   return 0;                                                                                                               }                                                                                                                           

fflush是刷新缓冲区的,此时你便会看到,先打印结果,再休眠3秒,关于缓冲区的具体知识,在我们学习到Linux后面的时候就会明白

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序

对于上述回车换行,我们见下一段代码:

代码语言:javascript代码运行次数:0运行复制
int main(){    int cnt = 10;    while(cnt)    {        printf("这是一个倒计时:%2d\r", cnt);        fflush(stdout);        cnt--;                                                                                                                                          sleep(1);    }    return 0;}

/r就是回车的作用,但是它没有刷新缓冲区的功能,所以我们每次要进行刷新缓冲区才能看到一个正常的倒计时,如下:

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序
✨2. 进度条程序

有了前面的知识铺垫,我们就可以写一个Linux下第一条小程序进度条如下所示:

【Linux】想学习Linux不看这一篇你就慢了-->工具篇(四)gdb、进度条程序

首先,需要101个字符数组,因为最后一个需要放‘\0’,因而需要101个空间

代码语言:javascript代码运行次数:0运行复制
#define NUM 101char pg[NUM];memset(pg, '\0', sizeof(pg));

其次需要对这个数组进行初始化,并且数组赋值肯定是在一个循环当中的,因此需要定义一个临时变量,一来控制循环,二来改变数组里面的值。对于%后面的小圈圈,我们可以让| \ - / 四个字符轮流转换视觉上就显示的是转圈圈。

代码语言:javascript代码运行次数:0运行复制
char cir[4] = {'|', '\\', '-', '/'};int cnt = 0;   while(cnt <= 100)                                                                                                                                       {        printf("[%-100s][%d%%][%c]\r", pg, cnt, cir[cnt % 4]);        fflush(stdout);        pg[cnt++] = STYLE;        usleep(50000);    }

对于fflush,与sleep上面例子有不再赘述,至于usleep是为了让它走得相对快些,让它5秒走完,粗略为100次循环,则每次是5/100 = 0.05,usleep是微秒,则0.05*1000000 = 50000,所以让它休眠50000微秒


?三、总结

本篇博客我们主要了解了 Linux 调试器 gdb 和 Linux 下的进度条程序。gdb 是一个命令行源代码级调试器,可用于调试多种编程语言,在 Linux 等系统中发挥重要作用,通过示例代码展示了其基本使用方法,如设置断点、查看变量等。同时,讲解了 Linux 下第一条程序 —— 进度条的实现,介绍了 printf 的缓冲机制以及如何利用相关函数实现动态进度条效果。希望大家有所收获!

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

557

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

394

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

756

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

478

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

454

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

1051

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

658

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

554

2023.09.20

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

9

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.6万人学习

Git 教程
Git 教程

共21课时 | 2.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号