Linux友人帐之调试器--gdb的使用 骑猪看日落 2024-04-17 13:35 23阅读 0赞 ## 一、debug和realease版本的区别 ## ### 区别 ### > debug是给程序员用的版本,添加了调试信息,用于解决软件或程序中出现的问题,realease是发行给客户使用的版本,并未添加调试信息,只需要给客户提供优越的产品使用环境即可,至于是否能够debug调试,这是程序员才应该关心的主要问题。 > > 可以看到debug版本的字节大小是要大于realease版本的,这是因为其中添加了调试信息。 ## ![9a021d1179a2441fb1fb028813451cbc.png][] ## 通过指令可以读取可执行程序的二进制构成,显示出具体的二进制软件的内部所形成的特定格式。 值得注意的是:每一个二进制程序不仅仅只是一堆二进制代码,他们内部都是有特定格式的,Linux中形成的可执行程序是elf格式。 ### readelf命令 ### > readelf命令是一个可以读取ELF(Executable and Linkable Format)文件头部信息的Linux命令。ELF文件是一种可执行文件和共享库的标准格式,包含了代码段、数据段、符号表和动态链接信息等。通过readelf命令,用户可以查看这些信息,如ELF文件的类型、入口地址、节区信息、符号表、重定位信息、动态链接信息等。 > > 常用的readelf命令选项包括: > > * \-a或--all:显示所有信息,默认选项; > * \-h或--file-header:显示文件头(包括ELF文件类型、入口地址等); > * \-S或--sections:显示节区信息; > * \-s或--symbols:显示符号表信息; > * \-r或--relocs:显示重定位信息; > * \-d或--dynamic:显示动态链接信息。 下面就是debug中所添加的调试信息,而realease版本是没有这些调试信息的 ![2046479e5e1142cbb3c58cf82b1d74ab.png][] ## 二、 调试器gdb ## ### 3.1gdb介绍 ### > gdb是GNU开源组织发布的一个用于Unix/Linux的程序调试工具。 > > 与其它调试器一样,gdb可以在程序中设置断点、查看变量值,跟踪程序执行的过程。 > > 利用调试器的这些功能可以方便地找出程序中存在的非语法错误。 ### 3.2环境配置 ### 安装 ![6b4c49295a2d461f92f3309cb6b411e6.png][]编写一个用于测试的程序test.c #include <stdio.h> int get_sum(int n) { int sum = 0, i; for (i = 1; i <= n; i++) sum += i; return sum; } int main() { int j = 100, res; res = get_sum(j); printf("1+2+...+%d = %d\n", j, res); return 0; } 编译并运行该程序 gcc -g test.c -o test 需要-g参数 ./test > 几点注意: > > * 默认情况下,gdb无法进行对gcc现在发布的程序进行调试,因为gcc默认生成的软件是realease版本的,没有调试信息,无法被调试器gdb调试,并且gcc是默认动态链接的,如果想静态链接还需要加static选项,所有gcc是有两种默认行为的。 > * gcc编译时添加-g选项可以使得gcc发布的程序软件为debug版本,这样就可以通过gdb对程序进行调试 ### 3.3gdb的启动和退出 ### > #### 启动: #### > > 1. gdb \[程序名\] > > gdb test > > 2. gdb --quiet > > ![675d589fbe46480cb02f987157158c41.png][] > > (gdb)file test > > ![f7d2adc98dc34a639f4be763eb9d2a4e.png][] > > #### 退出 #### > > (gdb)quit ### 3.4gdb常用命令 ### #### help命令 #### #### ![379253d12e5847f7adfe261b2f625251.png][] 其他命令 #### > #### 显示程序源代码list #### > > list: 输出从上次调用list命令开始向后的10行程序代码 > > list -: 输出从上次调用list命令处向前10行代码 > > list n: 输出n行附近的10行代码 > > list \[函数名\]: 输出函数附近的10行代码 > > list n1,n2: 显示第n1行到n2行的代码 > > #### 搜索字符串 #### > > forward/search \[字符串\]: 从当前位置向后查找指定的字符串所在的程序行,查找时不包括当前行,可以用list n,n将当前行设置为n > > reverse-search \[字符串\]: 从当前行向前查找第一个匹配的字符串 > > #### 执行程序 #### > > 在shell环境下使用gdb test,或在gdb环境下使用file test只是载入了程序,但是程序是没有运行的 > > 运行: > > (gdb)run ### 3.5断点的设置和管理 ### #### 设置断点 #### ##### 1 以行数设置断点 ##### 格式: break n 功能: 当程序运行到指定行时,会暂停执行,指定行的代码不执行 例如: (gdb)break 15 (gdb)run ##### 2 以函数设置断点 ##### 格式: break \[函数名\] 例如: (gdb)break get\_sum (gdb)run ##### 3 以条件表达式设置断点 ##### 格式: break \[行号或函数名\] if \[条件\] 功能: 程序在运行过程中,满足设定条件时,程序在所设置处中断 例如: (gdb)break 7 if i==99 含义: 当程序执行到第7行时,判断条件i==99是否成立,若成立则中断 ##### 4 以条件表达式变化设置断点 ##### 格式: watch \[条件表达式\] 功能: 程序在运行过程中,当满足设定条件时,程序中断 注意:watch必须在程序运行的过程中设置观察点,即运行run之后,并且要保证条件表达式中的变量已经使用过。 例1 (gdb)break 13 (gdb)run (gdb)watch sum==3 例2 (gdb)break 5 (gdb)run (gdb)watch sum==3 #### 查看断点 #### 查看当前设置的断点 格式: info breakpoints( **info b**) 例如: (gdb)break 7 (gdb)break 15 if res==5050 (gdb)info breakpoints![6172a595058e41db9896db331281771f.png][] #### 管理断点 #### ##### 1. 使中断失效或有效 ##### 失效: disable \[断点编号\] 有效: enable \[断点编号\] ##### 2. 删除断点 ##### clear \[行号\]: 删除此行的断点 delete \[断点编号\]: 删除指定编号的断点, 若有一次删除多个断点,各断点编号以空格分开。 delete: 删除程序中所有的断点 ##### 3. 取消断点 d + 断点编号 ##### #### 查看和设置变量的值 #### 当程序执行到中断点暂停时,往往需要查看变量或表达式的值,借此了解程序的执行状态,进而发现问题。 ##### 1 print ##### 功能: 打印变量或表达式的值,还可以用来对某个变量进行赋值。 print \[变量或表达式\]: 打印变量或表达式的值 print \[变量\]=\[值\]: 对变量进行赋值 例如: (gdb)break 7 (gdb)run (gdb)print i < n (gdb)print i (gdb)print sum (gdb)print i=200 (gdb)continue ##### 2 whatis ##### 功能: 用于显示某个变量或表达式的数据类型 格式: whatis \[变量或表达式\] 例如: (gdb)break 7 (gdb)run (gdb)whatis i (gdb)whatis sum (gdb)whatis sum+0.5 ##### 3 set ##### 功能: 给变量赋值 格式: set variable \[变量\]=\[值\] ##### 4.临时查看变量或地址的值:p + 变量或地址 ##### ![09776c378b06444a977e30f8caec6ed8.png][] #### 控制程序的执行 #### 当程序执行到指定的中断点时,完成相关的debug操作后,可以让程序继续运行 ##### 1 continue ##### 程序继续运行,直到下一个断点或运行完毕(运行至下一个断点处**:c(**continue)) ##### 2 kill ##### 结束当前程序的调试 ##### 3 next/step ##### 功能: 一次一条执行程序代码(**逐过程:n(next),逐过程:n(next)**) 区别: next把函数调用当做一条语句来执行;step追踪进入函数,一次一条地执行内部代码。 ##### 4.跳转到指定行:until+行号 ##### 可以利用until来跳出循环 ![0d7b9cf35d7040d7a63b5a38116fe408.png][] [9a021d1179a2441fb1fb028813451cbc.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/12/a1126dad41ee471190fef06f75d02a27.png [2046479e5e1142cbb3c58cf82b1d74ab.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/12/c8044c2c76c1467f824c0b85405396f4.png [6b4c49295a2d461f92f3309cb6b411e6.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/12/71e7cce4712548c9a330713685395214.png [675d589fbe46480cb02f987157158c41.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/12/6b43850f48454962932d75bd1dc236cb.png [f7d2adc98dc34a639f4be763eb9d2a4e.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/12/5c9ba40a244c4988a4f5ab5f7021ba64.png [379253d12e5847f7adfe261b2f625251.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/12/f17ce90eb0b04397b62667c607fdf372.png [6172a595058e41db9896db331281771f.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/12/89e1df93af89455180504e7ebf8afc52.png [09776c378b06444a977e30f8caec6ed8.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/12/3c000f21b98f495584cf85660b6fd31f.png [0d7b9cf35d7040d7a63b5a38116fe408.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/12/15c8f54636d64fa6b1adcebc0898f90f.png
还没有评论,来说两句吧...