『Linux』GDB调试

简介: 『Linux』GDB调试

前言

GDB 是由 GNU 软件系统社区提供的调试工具,同 GCC 配套组成了一套完整的开发环境,GDB 是 Linux 和许多类 Unix 系统中的标准开发环境。

一般来说,GDB 主要完成下面四个方面的功能:

启动程序:可以按照自定义的要求随心所欲的运行程序。

设置断点:可让被调试的程序在所指定的调置的断点处停住,断点可以是条件表达式。

打印信息:当程序被停住时,可以检查此时程序中所发生的事。

修改变量:可以通过修改程序中的变量,将一个 BUG 产生的影响修正从而测试其他 BUG。

debug版本与release版本

  • 假设存在一段代码:
//文件为 gdb_test.cpp
#include<iostream>
int GetSum(int n){ //主要是测试 ;其功能为计算1至n之和;
  int ret = 0;
  for(int i = 1;i<=n;++i){
    ret+=i;
  }
   return ret;
 }
 int main()
 {
   int n =0;
   std::cin>>n;
    int ret = GetSum(n);
    std::cout<<ret<<std::endl;
    return 0;                                                         
  }
  • 再使用g++进行编译:
g++ gdb_test.cpp -o test
  • 编译链接过后进行运行确保程序无误;
    在这时若是想使用gdb进行调试:
gdb test

(前提是得有gdb),若是没有gdb则需要使用yum进行安装:

sudo yum install -y gdb
  • 将会出现这样的提示:
    (no debugging symbols found) … done.
    没有找到调试符号
    这正是因为,在使用gcc/g++进行编译链接所生成的可执行文件默认是release版本的,无法进行debug调试;
    这里可以再回顾一下gcc/g++的特性;
链接 生成的可执行程序
gcc/g++ 在不使用-static修饰的时候默认为动态链接; 默认生成的可执行程序的版本为release版本,若是需要生成debug版本需要在末尾处加上-g

生成debug版本的可执行程序:

g++ gdb_test.cpp -o test_debug -g

添加-g选项代表该可执行程序为以debug方式发布的

生成debug版本的可执行程序后即可以进行调试;

gdb test_debug

在此之前可以使用readelf来查看ELF格式文件信息;

readelf -S 'filename' #使用-S选项显示节头信息

或者

readelf -S 'filename' | grep -i debug  #使用-S选项显示节头信息,grep debug为找出所有带debug的信息,-i为不区分大小写;

以第二条命令查看release版本的可执行程序的段信息时可以看到

由于没有debug,所以不显示;同时因为没有debug也不能进行调试;

同时使用第二条命令对所生成的debug版本的可执行程序时为

debug版本和release版本的大小差是因为在debug版本中多出了许多调试信息

在进行调试之前先使用Makefile以方便构造与清除


GDB操作

启动与退出gdb

gdb 'filename' #使用该命令即可启动gdb调试,其中filename为可执行程序(debug版)
quit #要退出gdb时只要输入quit或者q即可退出

显示代码

list #当然大多数情况下会使用简写 l ,从头开始即为 l 0 并回车至所有代码显示完毕

一般使用list时,gdb将会按照自己的方式将代码进行显示,可能不显示全,单若是希望从头开始显示时则可以使用 l 0 即从头显示代码,单此时也并不会显示完全,所以要用回车至所有代码显示完全;

同时在这里该注意,gdb与平时的Linux操作中较为不同的是;

在gdb调试过程中,gdb将会记住你上次的指令,这也是在使用list(或者l)后按照回车能够继续显示代码,在此处按回车时将会继续list的命令;


控制程序执行

命令 功能
run < arguments > 或者 r < arguments > 运行或者重新运行程序,并传递指定的参数。如果设置了断点,程序会在断点处暂停,并显示当前的源代码和寄存器值;
如 : run arg1 arg2 运行程序,并传递arg1和arg2为参数;
continue 或者 c 继续运行程序 (若是有断点则至下一个断点处停止,否则运行至程序结束)
next 或者 n 逐过程调试(不进入函数)
step 或者 s 逐行调试 (会进入函数)
finish 或者 f 执行程序至当前函数结束(返回),并显示返回值;
return < expression >或者 r < expression > 强制当前函数立即返回,并将返回值设定为指定的表达式。如果不指定表达式则返回0;
jump < location >或者 j < location > 强制程序跳转到指定位置,可以是行号、或者是地址;将可能改变程序的正常流程;

断点设置与取消:

命令 功能
(gdb) break main(main的这个位置可以是函数名、文件名: 、行号或者内存地址) 在main函数的第1行的位置设置断点(以此类推,所有的函数都可以像这样进行断点设置)
(gdb) break test.c:10 在同一目录下的test.c源文件设置断点(暂未证实,应该另有)
(gdb) info breakpoints 查看当前节点个数以及编号位置等信息;可以简写为i b 以此类推,但是此处的breakpoints并不能用来进行断点(不能使用breakpoints 10 这类的方式进行断点)
(gdb) delete 1 删除编号为1 的节点 ;delete也可以简写为d;
(gdb) delete 删除所有节点
condition <number编号> <expression表达式>或者cond <number编号> <expression表达式> 给指定编号的断点添加条件,当条件为真时,起到断点作用

查看(或修改)变量、寄存器与内存

命令 功能
print 或者 p 打印某个变量或者表达式的值。可以使用任何合法的C语言表达式,包括宏、指针、结构体等。
print x 打印变量x的值
print *p 打印指针p所指向的值
print add(10,20); 打印调用add函数并传入10 20作为参数后的返回值;
set < expression> 修改某个变量或者表达式的值,修改规则同上;
set x = 10 将变量x修改为10,同理该方法也同样可以用来修改指针
set add(10,20) = 100 修改调用函数并传递10与20作为参数后修改返回值为100
info registers或者i f 显示所有寄存器的值
info registers < name >或者i f 显示指定的寄存器的值
info registers eax 显示eax寄存器的值
set $< name > = < value > 修改寄存器的值
set $eax = 5 将寄存器eax 的值修改为5
相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
相关文章
|
10天前
|
存储 NoSQL Linux
linux之core文件如何查看和调试
通过设置和生成 core 文件,可以在程序崩溃时获取详细的调试信息。结合 GDB 等调试工具,可以深入分析 core 文件,找到程序崩溃的具体原因,并进行相应的修复。掌握这些调试技巧,对于提高程序的稳定性和可靠性具有重要意义。
49 6
|
25天前
|
运维 监控 Linux
BPF及Linux性能调试探索初探
BPF技术从最初的网络数据包过滤发展为强大的系统性能优化工具,无需修改内核代码即可实现实时监控、动态调整和精确分析。本文深入探讨BPF在Linux性能调试中的应用,介绍bpftune和BPF-tools等工具,并通过具体案例展示其优化效果。
46 14
|
2月前
|
缓存 NoSQL Linux
Linux调试
本文介绍了Linux调试、性能分析和追踪的培训资料,涵盖调试、性能分析和追踪的基础知识及常用工具。
252 6
Linux调试
|
2月前
|
NoSQL 编译器 C语言
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。
C语言调试是开发中的重要技能,涵盖基本技巧如打印输出、断点调试和单步执行,以及使用GCC、GDB、Visual Studio和Eclipse CDT等工具。高级技巧包括内存检查、性能分析和符号调试。通过实践案例学习如何有效定位和解决问题,同时注意保持耐心、合理利用工具、记录过程并避免过度调试,以提高编程能力和开发效率。
53 1
|
5月前
|
NoSQL Linux C语言
Linux GDB 调试
Linux GDB 调试
73 10
|
5月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
174 3
|
5月前
|
Ubuntu Linux
内核实验(四):Qemu调试Linux内核,实现NFS挂载
本文介绍了在Qemu虚拟机中配置NFS挂载的过程,包括服务端的NFS服务器安装、配置和启动,客户端的DHCP脚本添加和开机脚本修改,以及在Qemu中挂载NFS、测试连通性和解决挂载失败的方法。
292 0
内核实验(四):Qemu调试Linux内核,实现NFS挂载
|
5月前
|
NoSQL Linux 编译器
内核实验(一):使用QEMU+GDB断点调试Linux内核代码
如何配置环境并使用QEMU虚拟机结合GDB进行Linux内核代码的断点调试,包括安装QEMU、交叉编译工具链,编译内核以及通过GDB远程连接进行调试的详细步骤。
231 0
内核实验(一):使用QEMU+GDB断点调试Linux内核代码
|
5月前
|
NoSQL
技术分享:如何使用GDB调试不带调试信息的可执行程序
【8月更文挑战第27天】在软件开发和调试过程中,我们有时会遇到需要调试没有调试信息的可执行程序的情况。这可能是由于程序在编译时没有加入调试信息,或者调试信息被剥离了。然而,即使面对这样的挑战,GDB(GNU Debugger)仍然提供了一些方法和技术来帮助我们进行调试。以下将详细介绍如何使用GDB调试不带调试信息的可执行程序。
151 0
|
程序员 编译器 Linux
linux gdb-多线程调试
相信使用C/C++语言开发软件的程序猿们都经历过‘栈溢出’的问题。‘栈溢出’问题通常十分的隐蔽,有的时候问题复现也十分的困难。每当软件出现莫名其妙的问题时,总是有人怀疑是不是栈溢出了,但是问题的排查又十分的困难,所以,‘栈溢出’就是广大C/C++开发者的噩梦。
160 0