当前位置: 首页 > news >正文

【Linux】gdb调试器

目录

  • 什么是gdb
  • 怎么使用gdb
    • debug版与release版
    • 进入和退出调试状态
    • 代码打印
    • 运行程序
    • 打断点
    • 逐过程和逐语句调试
    • 变量打印
    • 快速跳过代码
    • 修改变量值
    • 查看调用堆栈

什么是gdb

gdb(GNU Debugger)是GNU项目中的一款功能强大的​​命令行调试工具​​,主要用于调试C、C++等编程语言编写的程序。它是开发者排查程序错误(如崩溃、逻辑错误、内存问题等)的核心工具之一,支持多种平台(Linux、Windows、macOS等)。其实说实在的,gdb本身说不上好用,在Windows、macOS等图形化界面(GUI)的操作系统上,因为图形化界面简洁明了,所以往往有着更好的选择。但是在Linux下,由于其是文本界面(TUI)的缘故,gdb已经是很好用很强大的工具了。

怎么使用gdb

debug版与release版

在vs上写过程序的应该见过,程序在编译时是有debug版与release版之分的,debug版的程序可以调试,release版的则不能,但是release版的程序会比debug版的跑的更快。为什么会这样呢?因为debug版的加入了调试信息,禁用了编译器的优化,保证代码严格按照代码顺序执行,确保调试能顺利进行,而release版则没有加入调试信息,对代码进行了极致优化,所以才出现了以上差别。在实际当中,代码在开发测试阶段会编译成debug版确保各种调试和错误排查工作的进行,代码正式上线时才会改成release版给到用户,从而确保代码足够快,性能足够高,保证用户的使用体验。所以想要使用gdb调试,毫无疑问要将代码编译成debug版,怎么编译呢?Linux中使用gcc/g++编译器编译时,默认是编译成release版的,我们需要加上-g选项才行。

g++ -o debug版目标文件 源文件 -g

进入和退出调试状态

使用指令,

gdb debug版目标文件

就会进入调试状态了。
在这里插入图片描述
这时我们会发现命令行前面变成了(gdb),这就表示我们进入调试状态了,这时使用指令q或quit,可以退出调试状态。
在这里插入图片描述

代码打印

在调试状态我们要是想要查看代码,我们可以使用指令list或l来打印,
在这里插入图片描述
默认是只会打印10行,如果我们想要继续往下看,可以再次使用指令,这时就会接着上次的行数往下打印10行,我们也能什么都输,直接回车,这时也会自动往下打印10行。

l 后面跟数字可以直接打印指定行数往下10行的代码,
在这里插入图片描述
我们也能指定函数名,打印指定函数附近的代码,
在这里插入图片描述
在有多个源文件时,我们也可以指定文件名来打印代码,使用指令

l/list 指定文件:行号

就行。
在这里插入图片描述
执行过一次之后按回车也能接着打印。

运行程序

使用指令r或run可以在调试状态运行程序
在这里插入图片描述

打断点

调试过程序的应该对断点都不陌生,打上断点的程序直接运行时会在断点处停下来,是很方便很实用的功能,gdb也是支持断点的。使用指令b或break可以打断点

b/break 数字

数字多少,就在对应的行号打上断点。

使用指令,

info b/break/breakpoints

可以查看断点信息。
在这里插入图片描述

字段含义
Num断点编号
Type断点类型
Disp命中后的处理方式
Enb是否启用
Address断点的内存地址
What断点位置描述

断点的编号是从1开始往下递增,每创建一个断点系统就会自动分配一个。断点类型分为breakpoint(普通代码断点)、watchpoint(数据断点,用于监视变量变化)、catchpoint(事件断点,捕捉异常/信号等),我们直接创建的就是普通断点,最为实用。断点命中后的处理方式有keep(保持启用(默认))、del(自动删除(一次断点))、dis(自动禁用(下次需要手动启用))。是否启用意味着断点是否在发挥作用,断点没有启用的话就和没有一样,程序不会在该断点处停下来了。断点的内存地址表示断点在内存中的绝对地址。断点位置描述表示断点在代码中的位置。

断点信息还会记录断点的命中次数,即实际运行时在断点处停下来的次数,上面的代码信息截图中第一个断点就显示breakpoint already hit 1 time,表示被命中过一次了,这是因为之前我已经r指令跑了一次,且在第一个断点处停了下来。

我们在有多个断点的程序中如果已经在一个断点处停下,想要程序运行到下一个断点处该怎么做呢?我们可以使用continue或c指令,这时代码就会继续运行到下一个断点处,如果没有断点了,就是跑到程序结束。

前面断点信息那里我也讲过,断点是可以设置启用或不启用的,我们在创建断点时默认断点是启用的,使用指令

disable 要禁用的断点编号

disable breakpoint 要禁用的断点编号

可以禁用指定的断点,如果我们不加数字编号,就会直接禁用所有的断点。禁用断点之后,我们想要恢复怎么办呢?使用指令

enable 启用断点

enable breakpoint 启用断点

可以启用断点。

我们使用b打断点时还可以指定函数名,这时断点就会打在指定函数的第一行,
在这里插入图片描述
我们同样也能在有多个源文件指定源文件来打断点,
在这里插入图片描述
最后需要注意,断点信息会在退出调试状态时全部清除。

逐过程和逐语句调试

我们在调试代码时,经常会用到逐过程和逐语句来进行调试。逐过程和逐语句在一般场景下是一样的,但是在遇到函数时就不一样了,逐过程的会直接跳过进入函数的过程,直接执行完这个函数,而逐语句会进入函数内一步步走。熟悉vs的都知道,在vs中,逐过程是F10,逐语句是F11,在gdb中,逐过程是指令n,逐语句是指令s。

需要注意的是,我们没法使用这条指令直接使程序运行起来,也就是我们无法像vs一样按F10或F11直接让程序一步一步的跑。n指令和s指令只能在程序跑起来但是没跑完时用,我们可以在想要仔细调试的位置设置断点,再r指令跑到断点处,然后使用n或s指令一步步跑。如果我们想要从一开始就一步步跑,我们可以在开头打一个断点,也可以使用指令start,这条指令会自动在main函数开头生成一个临时断点(用完自动清除),直接在开头停下来,这是我们就能使用n指令或s指令一步步跑了。
在这里插入图片描述
在使用n或s指令时,我们也能像打印代码一样,再输过一次指令之后直接回车自动重复刚刚的指令。

变量打印

我们在调试时,经常会想要关注变量的变化情况,vs中我们常用监视窗口来完成,gdb中我们也是有对应的指令的。

使用p指令可以直接打印变量值。
在这里插入图片描述
$1 是gdb自动创建的​​临时变量​,用来记录a的值,数字是gdb分配一个递增编号,从1开始,每使用一次就递增1。这个指令只能打印变量一次,可以对不那么想频繁关注的变量使用,如果我们想频繁地关注一个变量的变化情况,我们可以使用display指令常打印一个变量
在这里插入图片描述
此时我们使用n指令或s指令时下面会自动打印变量的值。如果我们不想要显示之前常打印的值时,可以使用undisplay指令指定显示变量的编号
在这里插入图片描述
这时就不会再打印这个变量了。

快速跳过代码

我们在实际调试代码时,可能会遇到想要暂时想要跳过一段的情况,这时用断点又不够方便,我们这时就可以用until指令
在这里插入图片描述
指定行号就能跑到到指定位子了除非中间有断点。我们有时在进入到函数内部之后觉得这个函数没什么问题,想要直接跑完这个函数,我们就可以使用finish指令,可以直接跑完当前函数。
在这里插入图片描述

修改变量值

我们在代码调试时有时会想要调整一个变量的值到一种极端情况看看会不会出错,gdb中我们可以直接使用指令

set var 变量=指定值

来修改。
在这里插入图片描述

查看调用堆栈

gdb中我们可以使用bt指令查看调用堆栈来检查程序运行情况,确认错误原因。
在这里插入图片描述

http://www.lqws.cn/news/471547.html

相关文章:

  • 蓝桥杯备赛篇(上) - 参加蓝桥杯所需要的基础能力 1(C++)
  • 偏微分方程通解求解2
  • 【RAG优化】深度解析开源项目MinerU:从PDF解析到多模态理解的工业级解决方案
  • 正则表达式与C++
  • 【Java】APi
  • rt-thread中使用usb官方自带的驱动问题记录
  • Compose笔记(二十八)--加水印
  • 【好用但慎用】Windows 系统中将所有 WSL 发行版从 C 盘迁移到 非系统 盘的完整笔记(附 异常处理)
  • 网络基础入门:从OSI模型到TCP/IP协议详解
  • Gartner《AI-Driven Methods for Cost-Efficiency》学习心得
  • SQL Server 数据库操作
  • 大模型的开发应用(十二):RAG 与 LlamaIndex基础
  • 【论文阅读】人工智能在直升机航空电子系统中的应用
  • 随机一道面试题1:Python是解释型语言or编译型语言?
  • 算法-Day04
  • SD-WAN 不是“裸跑”:聊聊怎么把网络安全绑在智能网关上
  • 2025zbrush雕刻笔记
  • DPO直接偏好函数的学习解读
  • C语言:最大公约数
  • 以AI赋能创意未来:即梦3.0与Seedance1.0Lite重磅登陆POE!
  • 操作系统内核态和用户态--2-系统调用是什么?
  • 新手如何利用AI助手Cursor生成复杂项目
  • LINUX621 NFS 同步 ;FTP;samba环境
  • 李宏毅2025《机器学习》第三讲-AI的脑科学
  • AI大模型学习之基础数学:微积分在AI大模型中的核心-梯度与优化(梯度下降)详解
  • FreeRTOS事件组(Event Group)
  • Rust调用 DeepSeek API
  • kibana和elasticsearch安装
  • Docker简单介绍与使用以及下载对应镜像(项目前置)
  • 《揭开CSS渲染的隐秘角落:重排与重绘的深度博弈》