【Linux系统编程】第十五弹---调试器gdb使用

2024-05-09 13:36

本文主要是介绍【Linux系统编程】第十五弹---调试器gdb使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】【Linux系统编程】

目录

1、背景

2、安装gdb

 3、gdb的使用

总结


1、背景

前面我们学习了文件编辑器,项目自动化构建工具,以及gcc编译器,但是在我们写代码的过程中不仅仅只有写代码,还有改bug的阶段,在VS在我们通过debug模式对代码进行调试,那么我们Linux中如何调试代码呢???

这就用到了我们这弹要学习的gdb调试器了。

必要知识:

程序的发布方式有两种,debug模式(能调试)和release模式(不能调试)。
Linux gcc/g++出来的二进制程序,默认是release模式
要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项。

★ debug版本可调试,那是因为编译器形成可执行程序的时候,会给可执行程序添加添加调试信息;而release版本不能调试。


2、安装gdb

根据我们前面讲解的几个工具,基本上都是需要先进行安装的,gdb也不例外。

如果没有安装,则会出现下面的提示。

[jkl@VMCentos7 dir.gdb]$ gdb
-bash: /usr/bin/gdb: No such file or directory  # 没有该文件或目录

 gdb的下载跟我们前面下载的工具也基本类似,使用yum工具。此处博主用的普通用户,需要加sudo。

sudo yum install -y gdb    # 输入该命令  

出现下面的样子就安装成功了。

 3、gdb的使用

在使用gdb之前得先编写一个C语言代码,并使用-g(debug)编译,才能进行调试。

1. 创建一个文件并编写相应的代码。

[jkl@VMCentos7 dir.gdb]$ touch test.c # 创建文件
[jkl@VMCentos7 dir.gdb]$ vim test.c   # 编写代码
[jkl@VMCentos7 dir.gdb]$ cat test.c   # 查看代码
#include<stdio.h>
int main()
{int i=0;for(i=0;i<10;i++){printf("%d\n",i);}return 0;
}

2. 以debug模式进行编译。

[jkl@VMCentos7 dir.gdb]$ gcc -o test-debug test.c -g  # debug模式需加-g
[jkl@VMCentos7 dir.gdb]$ ls
test.c  test-debug   # test-debug为可执行程序

 3. 如何确认为debug模式?

a. 对比release版本和debug版本可执行程序的大小。

因为debug版本会添加调试信息,必然文件大小比release版本大。

[jkl@VMCentos7 dir.gdb]$ gcc -o test test.c  # release版本生成可执行程序
[jkl@VMCentos7 dir.gdb]$ ll
total 60
-rwxrwxr-x 1 jkl jkl 25792 Apr  4 14:15 test
-rw-rw-r-- 1 jkl jkl   121 Apr  4 14:06 test.c
-rwxrwxr-x 1 jkl jkl 27008 Apr  4 14:09 test-debug  # 显然debug版本占用内存更大

b. 读取ELF格式的可执行程序

[jkl@VMCentos7 dir.gdb]$ readelf -S test-debug | grep -i debug[27] .debug_aranges    PROGBITS         0000000000000000  00004d94[28] .debug_info       PROGBITS         0000000000000000  00004dc4[29] .debug_abbrev     PROGBITS         0000000000000000  00004e8d[30] .debug_line       PROGBITS         0000000000000000  00004f22[31] .debug_str        PROGBITS         0000000000000000  00004f99
# debug版本有关于debug的信息
[jkl@VMCentos7 dir.gdb]$ readelf -S test | grep -i debug  # release版本没有debug信息
[jkl@VMCentos7 dir.gdb]$ 

4. 正式使用gdb 

语法:

gdb [选项] 被调试的可执行程序文件

常见选项:

-q:安静模式,不打印介绍信息和版本信息

默认情况会打印gdb的版本信息。

[jkl@VMCentos7 dir.gdb]$ gdb test-debug
GNU gdb (GDB) Red Hat Enterprise Linux 9.2-7.1.0.4.al8
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test-debug...
(gdb) # 此时已经进入了debug模式

 如果想不打印版本信息,则添加 -q 选项。

[jkl@VMCentos7 dir.gdb]$ gdb -q test-debug
Reading symbols from test-debug...
(gdb) 

查看源码:

list(简写 l): 查看源程序代码,默认显示10行,按回车键继续看余下的。 

运行程序:

 run(简写 r) :运行程序直到遇到 结束或者遇到断点等待下一个命令;

设置断点:

break(简写 b) :格式 b 行号,在某行设置断点;
info breakpoints(简写 i b) :显示断点信息

显示断点信息对应的含义:

  • Num:断点编号
  • Disp:断点执行一次之后是否有效 kep:有效 dis:无效
  • Enb: 当前断点是否有效 y:有效 n:无效
  • Address:内存地址
  • What:位置

单步执行 :

next (简写为 n):逐过程调试会执行下一行,当遇到函数调用时,会一次性执行完该函数,也就是说不会进到函数体内部,相当于VS中的逐过程(F10)。
 
step (简写为 s):单步调试时同样会执行下一行,当遇到函数调用时,会进入改函数体内部,相当于VS中的逐语句(F11)。

查看变量:

print     变量名   查看变量的值

whatis 变量名    查看变量类型

退出gdb:

用quit(简写q)命令退出gdb

指令使用: 

run:简记为 r ,其作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。
continue (简写c ):继续执行,到下一个断点处(或运行结束)
next:(简写 n),单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。
step (简写s):单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的。
until:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
until+行号: 运行至某行,不仅仅用来跳出循环
finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
call 函数(参数):调用程序中可见的函数,并传递“参数”,如:call gdb_test(55)
quit:简记为 q ,退出gdb

设置断点:

break n (简写b n):在第n行处设置断点。
(可以带上代码路径和代码名称: b 文件名:行号)
b fn1 if a>b:条件断点设置。
break func(break缩写为b):在函数func()的入口处设置断点,如:break cb_button。
delete 断点号n:删除第n个断点。
disable 断点号n:暂停第n个断点。
enable 断点号n:开启第n个断点。
clear 行号n:清除第n行的断点。
info b (info breakpoints) :显示当前程序的断点设置情况。
delete breakpoints:清除所有断点。

查看源码:

list :简记为 l ,其作用就是列出程序的源代码,默认每次显示10行。
list 行号:将显示当前文件以“行号”为中心的前后10行代码,如:list 12
list 函数名:将显示“函数名”所在函数的源代码,如:list main
list :不带参数,将接着上一次 list 命令的,输出下边的内容。

打印:

print 表达式:简记为 p ,其中“表达式”可以是任何当前正在被测试程序的有效表达式,比如当前正在调试C语言的程序,那么“表达式”可以是任何C语言的有效表达式,包括数字,变量甚至是函数调用。
print a:将显示整数 a 的值。
print ++a:将把 a 中的值加1,并显示出来。
print name:将显示字符串 name 的值。
print gdb_test(22):将以整数22作为参数调用 gdb_test() 函数。
print gdb_test(a):将以变量 a 作为参数调用 gdb_test() 函数。
display 表达式:在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值。如: display a。
watch 表达式:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序。如: watch a。
whatis :查询变量或函数。
info function: 查询函数。

查看运行信息:

where/bt :当前运行的堆栈列表。

bt backtrace 显示当前调用堆栈。

up/down 改变堆栈显示的深度。

set args 参数:指定运行时的参数。

show args:查看设置好的参数。

info program: 来查看程序的是否在运行,进程号,被暂停的原因。

分隔窗口:

layout:用于分割窗口,可以一边查看代码,一边测试:

layout src:显示源代码窗口

layout asm:显示反汇编窗口

layout regs:显示源代码/反汇编和CPU寄存器窗口

layout split:显示源代码和反汇编窗口

Ctrl + L:刷新窗口

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

这篇关于【Linux系统编程】第十五弹---调试器gdb使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

Python 字典 (Dictionary)使用详解

《Python字典(Dictionary)使用详解》字典是python中最重要,最常用的数据结构之一,它提供了高效的键值对存储和查找能力,:本文主要介绍Python字典(Dictionary)... 目录字典1.基本特性2.创建字典3.访问元素4.修改字典5.删除元素6.字典遍历7.字典的高级特性默认字典

使用Python构建一个高效的日志处理系统

《使用Python构建一个高效的日志处理系统》这篇文章主要为大家详细讲解了如何使用Python开发一个专业的日志分析工具,能够自动化处理、分析和可视化各类日志文件,大幅提升运维效率,需要的可以了解下... 目录环境准备工具功能概述完整代码实现代码深度解析1. 类设计与初始化2. 日志解析核心逻辑3. 文件处

一文详解如何使用Java获取PDF页面信息

《一文详解如何使用Java获取PDF页面信息》了解PDF页面属性是我们在处理文档、内容提取、打印设置或页面重组等任务时不可或缺的一环,下面我们就来看看如何使用Java语言获取这些信息吧... 目录引言一、安装和引入PDF处理库引入依赖二、获取 PDF 页数三、获取页面尺寸(宽高)四、获取页面旋转角度五、判断

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序