Linux 下 gdb 的使用

news2024/11/17 1:37:25

目录

  • 一、概述
    • 1、安装和启动 GDB
  • 二、 GDB 常用命令
    • 1、查看源码
    • 2、断点
      • 2.1 设置断点
      • 2.2 查看断点信息
      • 2.3 删除断点
      • 2.4 激活/禁用断点
      • 2.5 观察断点
      • 2.6 捕获信号
      • 2.7 线程中断
    • 3、查看信息
      • 3.1 查看数据
      • 3.2 查看内存
      • 3.3 查看栈信息
      • 3.4 查看栈帧信息
    • 4、运行、调试
      • 5、编辑和搜索


一、概述

GDB(GNU调试器)是一个功能强大的开源调试工具,可用于调试多种编程语言,包括 C、C ++、Fortran 等。它可以在运行过程中检查程序状态,设置断点以停止程序执行并观察变量值、内存状态等,并提供一系列命令和功能来辅助调试过程。

GDB 的主要功能包括以下几个方面:

  • 设置断点GDB 允许你在程序的某一行代码上设置断点,当程序执行到这一行时会暂停并等待调试命令。
  • 单步调试:通过单步调试,你可以逐行执行程序并观察每一行代码的执行情况,方便定位问题。
  • 查看变量和内存:在调试过程中,你可以查看各个变量的值,检查它们是否符合预期。同时,你还可以查看内存的内容,以了解程序的内部状态。
  • 捕捉错误GDB 可以帮助你捕捉程序的错误,包括内存访问错误、未处理的异常等。当程序发生错误时,GDB会在错误发生的地方停下来,并提供相关信息。
  • 远程调试:在某些情况下,你可能需要在远程机器上进行调试。GDB 支持远程调试,你可以通过网络连接到远程机器,并在该机器上进行调试操作。

更多信息可以查看 GDB 官网。

1、安装和启动 GDB

首先输入命令:gdb -v 查看是否安装过 GDB:

如果没有安装则输入(Ubuntu 下):

# sudo apt-get install gdb

然后就可以启动 gdb 进行调试了。通过输入如下命令来启动 gdb 调试,直接指定需要调试的可执行文件名即可:

# gdb test_file

当下方出现图中圈中的字段则表示可调试。而如果出现了下图中的字段则表示无法调试:


使用常规编译生成的可执行文件正常一定会出现 No debugging symbols found in xxx 这个错误。而且即使使用带调试信息 -g 编译时,有时候也会出现这种情况。

解决方法如下:

我们先使用 -c -g 生成带调试信息的只进行过预处理、编译、汇编,但没有被链接的目标文件,再利用目标文件链接、重定位后生成可执行文件,使用这个可执行文件便不会出现问题。

$ gcc -c -g test_file.c # 生成 test_file.o 文件 
$ gcc test_file.o -o test_file

如果目标执行文件要求出入参数(如 argv[] 接收参数),则可以通过如下三种方式指定参数:

  1. 在启动 gdb 时,gdb --args text_file
  2. 在进入 gdb 之后,运行 set args param_1
  3. 在进入 gdb 调试以后,run param_1 或者 start param_1

其中的 param_1 是你自己要输入的参数。

二、 GDB 常用命令

以下以 test_file.c 作为源程序例子的名字,test_file 作为可执行文件例子的名字, 以 param_1 作为参数的例子的名字。

格式说明:

(gdb) 表示是在 GDB 调试页面输入的命令

p(print):表示 p 是 print 指令的缩写

// test_file.c
#include <stdio.h>
  
void swap(int *x, int *y)
{
    int t = *x;
    *x = *y;
    *y = t;
}

int main(void)
{
    int a = 10;
    int b = 20;

    printf("a = %d, b = %d\r\n", a, b);

    swap(&a, &b);

    printf("a = %d, b = %d\r\n", a, b);

    return 0;
}

然后再用上一节提到过的方法生成可执行文件。

1、查看源码

(gdb) l(list) [函数名][行数]

输入 llist 即可

如果直接输入 l 则会直接从文件第一行开始打印,一次打印 10 行,直到文件尾:

可以看到,GDB 会自动记忆我们上次敲入的指令。

当然,如果想看指定行的代码,则在 l 后面加上一个行号即可:

同理,如果想看指定函数的代码,则在 l 的后面加上指定的函数名即可:

2、断点

2.1 设置断点

  • break + [源代码行号][源代码函数名][内存地址]
  • break … if condition
    • …可以是上述任一参数;condition 是条件。例如在循环体中可以设置 break ... if i = 100 来设置循环次数

  • tbreak:tbreak 命令可以看到是 break 命令的另一个版本,tbreak 和 break 命令的用法和功能都非常相似,唯一的不同在于,使用 tbreak 命令打的断点仅会作用 1 次,即使程序暂停之后,该断点就会自动消失。
  • rbreak:和 break 和 tbreak 命令不同,rbreak 命令的作用对象是 C、C++ 程序中的函数,它会在指定函数的开头位置打断点。

2.2 查看断点信息

(gdb) info b

若是直接执行 info 的话,出来的就是所有的调试信息:


但若是我们只想查看一下所打的断点的信息,那就在后面加个 b/breakpoint

六个字段的含义如下:

  • Num : 编号
  • Type : 类型
  • Disp : 状态
  • Enb : 是否可用
  • Address : 地址
  • What : 在此文件的哪个函数的第几行

2.3 删除断点

(gdb) clear location

参数 location 通常为某一行代码的行号或者某个具体的函数名。当 location 参数为某个函数的函数名时,表示删除位于该函数入口处的所有断点。

(gdb) d(delete) [breakpoints] [num]

输入 breakpoints 参数表示删除所有断点;num 参数为指定断点的编号,表示删除指定编号的断点。


2.4 激活/禁用断点

(gdb) disable b(breakpoints) 	  	   # 使所有断点无效【默认缺省】
(gdb) enable b(breakpoints)  	  	   # 使所有断点有效【默认缺省】
(gdb) disable b(breakpoint) + [编号...] # 使一个或多个断点无效【禁用断点】
(gdb) enable b(breakpoint) + [编号...]  # 使一个或多个断点有效【开启断点】

(gdb) enable b(breakpoints) once [num...]   # 临时激活以 num... 为编号的多个断点,但断点只能使用 1 次,之后会自动回到禁用状态
(gdb) enable b(breakpoints) count [num...]  # 临时激活以 num... 为编号的多个断点,断点可以使用 count 次,之后进入禁用状态
(gdb) enable b(breakpoints) delete [num...] # 激活 num... 为编号的多个断点,但断点只能使用 1 次,之后会被永久删除。

2.5 观察断点

watch:此命令打的是观察断点,可以监控某个变量或者表达式的值。只有当被监控变量(表达式)的值发生改变,程序才会停止运行。

(gdb) watch cond

cond 代表的就是要监控的变量或者表达式。

rwatch 命令:只要程序中出现读取目标变量(表达式)的值的操作,程序就会停止运行;
awatch 命令:只要程序中出现读取目标变量(表达式)的值或者改变值的操作,程序就会停止运行。
catch:捕捉断点的作用是,监控程序中某一事件的发生,例如程序发生某种异常时、某一动态库被加载时等等,一旦目标时间发生,则程序停止执行。

总结:

观察断点
watch + [变量][表达式] :当变量或表达式值改变时即停住程序。
rwatch + [变量][表达式] :当变量或表达式被读时,停住程序。
awatch + [变量][表达式]:当变量或表达式被读或被写时,停住程序。

设置捕捉点
catch + event:当 event 发生时,停住程序。

其中,catch 指令的参数 event 参数表示要监控的具体事件。常用的 event 事件类型如下表所示:

event 事件含义
throw [exception]当程序中抛出 exception 指定类型异常时,程序停止执行。
如果不指定异常类型(即省略 exception),则表示只要程序发生异常,程序就停止执行。
catch [exception]当程序中捕获到 exception 异常时,程序停止执行。
exception 参数也可以省略,表示无论程序中捕获到哪种异常,程序都暂停执行。
load [regxep]
unload [regexp]
其中,regexp 表示目标动态库的名称,
load 命令表示当 regexp 动态库加载时程序停止执行;
unload 命令表示当 regexp 动态库被卸载时,程序暂停执行。
regexp 参数也可以省略,此时只要程序中某一动态库被加载或卸载,程序就会暂停执行。

除此之外,还有几个比较特殊的 event:

  • exec:调用系统调用 exec 时。(exec 为关键字,目前此功能只在 HP-UX 下有用)
  • fork:调用系统调用 fork 时。(fork 为关键字,目前此功能只在 HP-UX 下有用)
  • vfork:调用系统调用 vfork 时。(vfork 为关键字,目前此功能只在 HP-UX 下有用)

在这里插入图片描述

2.6 捕获信号

(gdb) handle + [argu] + signals
  • signals:是 Linux/Unix 定义的信号,SIGINT 表示中断字符信号,也就是 Ctrl+C 的信号,SIGBUS 表示硬件故障的信号;SIGCHLD 表示子进程状态改变信号; SIGKILL 表示终止程序运行的信号......
  • argu
    • nostop:当被调试的程序收到信号时,GDB 不会停住程序的运行,但会打出消息告诉你收到这种信号。
    • stop:当被调试的程序收到信号时,GDB 会停住你的程序。
    • print:当被调试的程序收到信号时,GDB 会显示出一条信息。
    • noprint:当被调试的程序收到信号时,GDB 不会告诉你收到信号的信息。
    • pass or noignore:当被调试的程序收到信号时,GDB 不处理信号。这表示,GDB 会把这个信号交给被调试程序会处理。
    • nopass or ignore:当被调试的程序收到信号时,GDB 不会让被调试程序来处理这个信号。

2.7 线程中断

(gdb) break [linespec] thread [threadno] [if ...]
  • linespec:断点设置所在的源代码的行号。如: test.c:12 表示文件为 test.c 中的第 12 行设置一个断点。
  • threadno:线程的 ID。是 GDB 分配的,通过输入 info threads 来查看正在运行中程序的线程信息。
  • if …:设置中断条件。

3、查看信息

3.1 查看数据

(gdb) p(print) variable 查看变量
(gdb) p(print) *array@len 查看数组(array 是数组指针,len 是需要数据长度)

可以通过添加参数来设置输出格式:

  • / :按十六进制格式显示变量。
  • /d :按十进制格式显示变量。
  • /u :按十六进制格式显示无符号整型。
  • /o :按八进制格式显示变量。
  • /t :按二进制格式显示变量。
  • /a :按十六进制格式显示变量。
  • /c :按字符格式显示变量。
  • /f :按浮点数格式显示变量。

但是一个一个地去 print 太过于繁琐,于是可以用 display!

display:跟踪查看一个变量,每次停下来都显示它的值(变量/结构体…)


同理,也可以用来追踪地址信息:

如果不想追踪某个变量了,就可以用 undisplay 指令取消对该变量的追踪:

(gdb) undisplay + 变量名编号

3.2 查看内存

(gdb) x(examine) /n f u + 内存地址(指针变量)
  • n 表示显示内存长度
  • f 表示输出格式(见 print)
  • u 表示字节数制定(b 单字节;h 双字节;w 四字节;g 八字节;默认为四字节)

3.3 查看栈信息

(gdb) bt(backtrace) [-full][-n][n]
  • -full 打印栈帧信息的同时,打印出局部变量的值。
  • n 表示只打印栈顶上 n 层的栈信息。
  • -n 表示只打印栈底上 n 层的栈信息。
  • 不加参数,表示打印所有栈信息。

3.4 查看栈帧信息

(gdb) info frame

该命令会依次打印出当前栈帧的如下信息:

  • 当前栈帧的编号,以及栈帧的地址;
  • 当前栈帧对应函数的存储地址,以及该函数被调用时的代码存储的地址
  • 当前函数的调用者,对应的栈帧的地址;
  • 编写此栈帧所用的编程语言;
  • 函数参数的存储地址以及值;
  • 函数中局部变量的存储地址;
  • 栈帧中存储的寄存器变量,例如指令寄存器(64 位环境中用 rip 表示,32 为环境中用 eip 表示)、堆栈基指针寄存器(64 位环境用 rbp 表示,32 位环境用 ebp 表示)等。

除此之外,还可以使用 info args 命令查看当前函数各个参数的值;使用 info locals 命令查看当前函数中各局部变量的值。

4、运行、调试

(gdb) r(run)

运行代码。如果有断点,会在断点处停下;否则会直接运行到程序结束。

(gdb) c(continue) 

程序在断点处停下来,通过 continue 指令让程序继续执行到下一个断点,没有断点的话则直接运行到程序结束。

(gdb) n(next) n

参数 n 表示单步执行多少行代码,默认为 1 行。其最大的特点是当遇到包含调用函数的语句时,无论函数内部包含多少行代码,next 指令都会一步执行完。也就是说,对于调用的函数来说,next 命令只会将其视作一行代码

(gdb) s(step) n

参数 n 表示一次执行的行数,默认为 1 行。通常情况下,step 命令和 next 命令的功能相同,都是单步执行程序。不同之处在于,当 step 命令所执行的代码行中包含函数时,会进入该函数内部

(gdb) until [location]
  • 不带参数的 until 命令,可以使 GDB 调试器快速运行完当前的循环体,并运行至循环体外停止。注意,until 命令并非任何情况下都会发挥这个作用,只有当执行至循环体尾部(最后一行代码)时,until 命令才会发生此作用;反之,until 命令和 next 命令的功能一样,只是单步执行程序
  • (gdb) until location:参数 location 为某一行代码的行号

下面的例子紧接着上面 step 指令的例子:

(gdb) finish

通过 finish 函数,可以直接让一个函数执行完毕,直接回到了调用函数的位置。

该例和 until 类似:

5、编辑和搜索

(gdb) edit [location]
(gdb) edit [filename]:[location]

location 表示程序中的位置。这个命令表示激活文件的指定位置,然后进行编辑。

输入以下两种格式都可以:

在这里插入图片描述

(gdb) search <regexp>
(gdb) reverse-search <regexp>

第一项命令格式表示从当前行的开始向前搜索,后一项表示从当前行开始向后搜索。

其中 regexp 就是正则表达式,正则表达式描述了一种字符串匹配的模式,可以用来检查一个串中是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MacOS安装 Python 和 PyCharm

MacOS安装 Python3.12.5 和 PyCharm 小阿呜有话说一、MacOS安装PythonPython官网下载 二、MacOS安装PyCharmPyCharm官网下载 叮嘟&#xff01;这里是小啊呜的学习课程资料整理。好记性不如烂笔头&#xff0c;今天也是努力进步的一天。一起加油进阶吧&#xff01; 小阿呜有话说 …

发完朋友圈就“退款”?黑神话的玩家是否都是“忠实粉丝”?

​声明&#xff1a;此篇为 ai123.cn 原创文章&#xff0c;转载请标明出处链接&#xff1a;https://ai123.cn/2228.html 《黑神话&#xff1a;悟空》自上线以来&#xff0c;便引发了玩家社区的广泛讨论。游戏的退款现象主要受到了一些技术问题和个人体验差异的影响。部分玩家因遇…

容器的ip地址不稳定问题、联合文件系统、核对时间、制作基础镜像

在docker中部署线上考试系统 1、部署前端服务器 # 上传本地下载的dist文件&#xff0c;因为上传的是目录&#xff0c;加-r选项 scp -r D:\云计算\压缩包\项目\dist root192.168.2.50:/root/ # 创建基础容器 [rootdocker ~]# docker run -it --name c0 centos:latest /bi…

SolidityFoundry BitMap

写合约的时候&#xff0c;记录某个账户的bool状态很常见&#xff0c;例如是否领取空投等&#xff0c;传统的写法mapping(uint256>bool)中一个slot只能存储一个账户的信息&#xff0c;在其他语言中&#xff0c;我们经常会用到bitmap来表示标志位&#xff0c;如果我们可以将bi…

银行卡三要素验证如何用Java进行调用

一、什么是银行卡三要素验证&#xff1f; 银行卡三要素验证又叫银行卡三要素核验、银行卡三要素校验、银行卡实名认证、银行卡三元素验证&#xff0c;即输入银行卡卡号、姓名、身份证号码&#xff0c;验证此三要素是否一致&#xff0c;该接口支持所有带银联标识的银行卡。 二…

langchain入门系列之五 初探代理

代理的核心思想是使用LLM来选择要采取的一系列动作。 在链式结构中&#xff0c;一系列动作是硬编码的&#xff08;在代码中&#xff09;。 在代理中&#xff0c;使用语言模型作为推理引擎来确定要采取的动作及其顺序。 代理 这是负责决定下一步采取什么动作的类。 这是由语言…

lidar3607.2 lidar360mls7.2 强大的雷达点云数据处理应用软件

1、LiDAR360是一款强大的激光雷达点云数据处理和分析平台&#xff0c;拥有超过10种先进的点云数据处理算法&#xff0c;可同时处理超过300G点云数据。平台包含丰富的编辑工具和自动航带拼接功能&#xff0c;可为地形、林业、矿山和电力行业&#xff08;参考LiPowerline软件&…

【HarmonyOS 4.0】@BuilderParam 装饰器

1. BuilderParam 装饰器 BuilderParam 装饰器用于装饰自定义组件(struct)中的属性&#xff0c;其装饰的属性可作为一个UI结构的占位符&#xff0c;待创建该组件时&#xff0c;可通过参数为其传入具体的内容。参数必须满足俩个条件&#xff1a; 2.1 参数类型必须是个函数&#x…

前端使用canvas绘制简单工作流-react

效果图如下&#xff1a; 目前只做了绘制部分&#xff0c;绘制方式也比较简单&#xff0c;点击工具栏中需要绘制的图形&#xff0c;在画布上左键点击将会绘制一个图形出来&#xff0c;工具栏选中第一个&#xff0c;再点击其他图像&#xff0c;长按鼠标左键可以移动&#xff0c;删…

丢掉Beyond Compare吧!新款文件差异对比工具WinMerge更具性价比!

今天想和大家分享一款非常实用的免费开源文件比较工具&#xff1a;WinMerge。 作为一名长期从事互联网行业的人&#xff0c;我经常需要处理大量的文档和代码文件&#xff0c;文件对比工具在我的日常工作中可谓是必不可少的“左膀右臂”。 也相信很多朋友在处理多个文档内容或者…

96页PPT集团战略解码会工具与操作流程

德勤集团在战略解码过程中通常会用到以下一些具体工具&#xff1a; 一、平衡计分卡&#xff08;Balanced Scorecard&#xff09; 财务维度&#xff1a; 明确关键财务指标&#xff0c;如营业收入、利润、投资回报率等。你可以通过分析历史财务数据和行业趋势&#xff0c;确定…

HUSB381A:带线PD适配器的绝佳选择

HUSB381A是慧能泰半导体全新推出的一款采用SOP8封装&#xff0c;集成MOS的USB PD Source芯片&#xff0c;带CC1和CC2引脚&#xff0c;支持不可分离线缆&#xff08;Captive Cable&#xff09;PD适配器和纯PD快充充电器应用。HUSB381A支持最大功率20V5A 100W应用&#xff0c;支持…

单片机驱动彩屏最简方案:单片机_RA8889最小开发板驱动控制TFT彩屏介绍(一)方案架构

本文介绍使用单片机RA8889来驱动和控制彩屏的最小方案。文章从RA8889的架构功能、硬件电路设计及软件设计三个方面来说明。 小编已发布多篇文章介绍了单片机RA8889来驱动控制彩屏&#xff0c;但是仍有不少单片机玩家可能对驱动彩屏还不算熟悉&#xff0c;在此加推一个短篇介绍…

审计发现 FBI 的数据存储管理存在重大漏洞

据The Hacker News消息&#xff0c;美国司法部监察长办公室 &#xff08;OIG&#xff09; 的一项审计发现&#xff0c; FBI 在库存管理和处置涉及机密数据的电子存储媒体方面存在“重大漏洞”。 OIG 的审计显示&#xff0c;FBI 对包含敏感但未分类 &#xff08;SBU&#xff09…

橙子投屏,轻松连接大屏幕

对于某腾、某爱、某酷投屏大家在熟悉不过了吧&#xff0c;一款非常好用的投屏软件&#xff0c;但是使用起来还是限制颇多&#xff0c;比如有犷郜&#xff0c;还必须同步使用手机App才能实现投屏功能&#xff0c;关键还得开会员&#xff0c;劝退不少小伙伴。但是现在手机往往占据…

API代理指南:跨境业务的数据桥梁

在当今全球化的经济环境中&#xff0c;跨境业务已成为企业拓展国际市场、实现业务增长的重要途径。但面临着法律法规差异、网络复杂性和数据安全等诸多挑战。为了有效应对这些挑战&#xff0c;API&#xff08;应用程序编程接口&#xff09;代理成为了跨境业务中不可或缺的一部分…

接口自动化框架设计必备利器之参数传递

在我们设计自动化测试框架的时候&#xff0c;我们会经常将测试数据保存在外部的文件&#xff08;如Excel、YAML&#xff09;中&#xff0c;实现测试脚本与测试数据解耦&#xff0c;方便后期维护。 当涉及到业务场景接口用例时&#xff0c;由于接口与接口存在关联关系&#xff…

5步掌握Python Django开发办公管理系统核心技巧

&#x1f393; 作者&#xff1a;计算机毕设小月哥 | 软件开发专家 &#x1f5a5;️ 简介&#xff1a;8年计算机软件程序开发经验。精通Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等技术栈。 &#x1f6e0;️ 专业服务 &#x1f6e0;️ 需求定制化开发源码提…

Unity实现棋盘方格

本文参考&#xff1a;p1_哔哩哔哩_bilibili 一、精要提炼 1、Button自带的白色底图是圆角的&#xff0c;Image组件自带的白色底图是方角的。 2、2D中Instantiate指定的位置为屏幕坐标系的位置&#xff0c;左下角为(0,0) 3、求某个组件的位置&#xff1a;xx.transform.posi…

(javaweb)事务管理+AOP

目录 1.spring事务管理 2.rollbackFor&#xff08;异常回滚属性&#xff09; 3.propagation&#xff08;事物传播行为&#xff09; AOP基础 1.AOP概述 AOP快速入门 AOP核心概念 APO进阶 1.通知类型 2.通知顺序 3.切入点表达式 4.连接点 5.AOP案例 1.spring事务管理…