0


[linux开发工具]小程序--进度条、调试器 - gdb


📙 作者简介 :RO-BERRY
📗 学习方向:致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识
📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持


请添加图片描述


目录


1.缓冲区

  • 第一种情况在这里插入图片描述 执行结果如下:请添加图片描述 可以看到程序先执行printf再执行sleep
  • 第二种情况在这里插入图片描述 执行结果如下:请添加图片描述

在这里为什么程序先执行sleep在执行printf呢?
实际上也并没有先执行sleep再执行printf,C语言执行代码是顺序结构自上往下
在这里运行的时候,程序运行sleep的时候printf早就运行完毕了
我们程序休眠之前没有看到字符串,那么我们输出的字符串一定是被保护起来了,在退出的时候才刷新出来
那么在sleep期间在哪里保存呢?
下面我们引出一个概念- - -缓冲区。

其实上面的现象中,在程序执行 printf 后,printf 打印的内容被存放到缓冲区中,在 C/C++ 中,会针对标准输出,给我们提供默认的缓冲区,而在缓冲区没有被刷新之前,我们的内容就不会被输出。
而 \n 就是一种刷新的策略 - - - 行刷新。所以我们加了 \n 后缓冲区被刷新,随即便打印出内容。
而我们没有使用 \n 的时候缓冲区并没有被刷新,但是我们可以使用 fflush(stdout) 强制刷新缓冲区,从而打印出内容,例如:
在这里插入图片描述
执行结果如下:
请添加图片描述
我们可以看到,缓冲区的内容被强制刷新出来了。

2)\n 和 \r

我们首先编写一个简单的倒计数程序,例如:
在这里插入图片描述
观察结果:
请添加图片描述
但是这并不是我们想要的倒计时,我们是期望在同一行中显示出来,所以我们不应该用 \n,其实 \n 就是我们所说的回车,就是使光标换行并回到那一行的最初位置;这时候我们就应该使用 \r,\r 就仅仅让光标回到当前行的最初位置,我们对上面的代码修改,如下:
在这里插入图片描述
执行结果如下:
在这里插入图片描述
从上面的结果可看出,我们的倒计时虽然在同一行了,但是输出的格式还是有问题,因为默认 %d 是按照一个字符的形式打印的,我们是要按照两个字符打印,所以我们仅需将%d修改为%2d即可,如下:
在这里插入图片描述
结果如下:
在这里插入图片描述
这时候就基本完成我们的倒计时了,但是倒计时到个位数的时候,前面空了一个字符,不太美观,这是因为 %2d 是默认右对齐,我们在前面加上负号,就是左对齐了,所以我们继续修改:
在这里插入图片描述
结果如下:
在这里插入图片描述
到此我们的倒计数就完成了。

3.进度条

ProgressBar.c

#include"ProgressBar.h"constchar*str ="|/-\\";// 加载光标voidProgressBar_v1(){// 当前进度int rate =0;char bar[SIZE];memset(bar,'\0',sizeof(bar));// 加载光标的数组长度int num =strlen(str);// 当进度没有加载满while(rate <= MAX_RATE){printf("[%-100s][%d%%][%c]\r", bar, rate, str[rate % num]);fflush(stdout);usleep(STIME);                    
       bar[rate++]= STYLE;}printf("\n");}

ProgressBar.h

#include<stdio.h>#include<unistd.h>#include<string.h>voidProgressBar_v1();#defineSIZE101//数组大小#defineMAX_RATE100//加载进度最大值#defineSTYLE'#'//加载符号#defineSTIME1000*40//时间

Makefile

ProgressBar:main.c ProgressBar.c
   gcc -o $@ $^.PHONY:clean
clean:
     rm -f ProgressBar     

main.c

#include"ProgressBar.h"intmain(){ProgressBar_v1();return0;}

我们在使用延时函数的时候使用了 usleep 函数,它与 sleep 相比就是,sleep 中以 s 为单位;usleep 中以 us 为单位。
运行成果:
在这里插入图片描述


4.认识gdb

gdb是什么

gdb是一个调试程序
程序中出现的语法错误可以借助编译器解决;但逻辑错误则只能靠自己解决。实际场景中解决逻辑错误最高效的方法,就是借助调试工具对程序进行调试。

所谓调试(Debug),就是让代码一步一步慢慢执行,跟踪程序的运行过程。比如,可以让程序停在某个地方,查看当前所有变量的值,或者内存中的数据;也可以让程序一次只执行一条或者几条语句,看看程序到底执行了哪些代码。

也就是说,通过调试程序,我们可以监控程序执行的每一个细节,包括变量的值、函数的调用过程、内存中数据、线程的调度等,从而发现隐藏的错误或者低效的代码。

程序的发布方式有两种,debug模式和release模式
Linux gcc/g++出来的二进制程序,默认是release模式
要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项
debug为可以调试的版本,release为优化后的版本也就是测试版本了
Linux gcc/g++出来的是二进制文件,默认是release版本。
在VS中,我们可以按F10进入调试
在Linux我们依旧可以调试,要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项

Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。
Release 称为发布版本,不包含调式信息,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
所以我们说调试就是在Debug版本的环境中,找代码中潜伏的问题的一个过程。

"Debug"和"Release"是软件开发过程中常见的两种构建(Build)配置。

  • Debug(调试)配置:

Debug 配置旨在方便开发人员在代码中进行调试和排查错误。
在 Debug 模式下,编译器会生成带有调试符号信息的可执行文件,这些符号信息包含了变量名、函数名和源代码行号等,以便在调试过程中能够准确地追踪错误。
Debug 配置通常会禁用一些优化,以便在调试过程中能够更好地观察程序的行为。
此配置的构建速度较慢,生成的可执行文件较大。

  • Release(发布)配置:

Release 配置旨在生成用于最终发布的、优化后的代码。
在 Release 模式下,编译器会对代码进行优化,以提高程序的执行效率和性能。
由于优化的存在,生成的可执行文件可能没有调试符号信息,并且可能会合并和删除一些不必要的代码。
Release 配置通常会启用各种优化策略,例如内联函数、循环展开和减少函数调用开销等,以提高代码的执行速度和资源利用率。
此配置的构建速度较快,生成的可执行文件较小。

在实际开发中,通常会使用 Debug 配置进行代码的开发、调试和测试,以便于快速定位和修复问题。而在准备发布软件时,会切换到 Release 配置,以生成性能更高、体积更小的最终可执行文件。

那在Linux上gcc/g++编译生成的可执行程序其实默认是release版本的,不包含调式信息,所以我们无法调式!

gdb的作用

GDB 全称“GNU symbolic debugger”,从名称上不难看出,它诞生于 GNU 计划(同时诞生的还有 GCC、Emacs 等),是 Linux 下常用的程序调试器。发展至今,GDB 已经迭代了诸多个版本,当下的 GDB 支持调试多种编程语言编写的程序,包括 C、C++、Go、Objective-C、OpenCL、Ada等。实际场景中,GDB 更常用来调试 C 和 C++程序。

总的来说,借助 GDB调试器可以实现以下几个功能:

  1. 程序启动时,可以按照我们自定义的要求运行程序,例如设置参数和环境变量;
  2. 可使被调试程序在指定代码处暂停运行,并查看当前程序的运行状态(例如当前变量的值,函数的执行结果等),即支持断点调试;
  3. 程序执行过程中,可以改变某个变量的值,还可以改变代码的执行顺序,从而尝试修改程序中出现的逻辑错误。

5、gdb的使用

GDB安装

1、通过包管理器进行安装

$ yum -y install gdb

2、源码安装GDB

在gdb源码包上面下载相应的版本进行安装即可。

3、查看GDB版本

输入

gdb -v

,即可查看当前安装的gdb的版本。
在这里插入图片描述
如果显示出gdb的版本,也说明了安装成功。

GDB的用法

GDB 的主要功能就是监控程序的执行流程。这也就意味着,只有当源程序文件编译为可执行文件并执行时,并且该文件中必须包含必要的调试信息(比如各行代码所在的行号、包含程序中所有变量名称的列表(又称为符号表)等),GDB才会派上用场。

所以在编译时需要使用 gcc/g++ -g 选项编译源文件,才可生成满足 GDB 要求的可执行文件
gdb常用指令:

  • list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。

  • list/l 函数名:列出某个函数的源代码。

  • r或run:运行程序。

  • n 或 next:单条执行(逐过程执行)。

  • s或step:进入函数调用(逐语句执行)

  • break(b) 行号:在某一行设置断点 break 函数名:在某个函数开头设置断点

  • d 编号 :删除断点

  • info break :查看断点信息。

  • finish:执行到当前函数返回,然后停下来等待命令

  • print§:打印表达式的值,通过表达式可以修改变量的值或者调用函数

  • 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 小程序 运维

本文转载自: https://blog.csdn.net/weixin_60521256/article/details/136176988
版权归原作者 RO-BERRY 所有, 如有侵权,请联系我们删除。

“[linux开发工具]小程序--进度条、调试器 - gdb”的评论:

还没有评论