深入了解Linux —— 调试程序
前言
我们已经学习了
linux下许多的工具,vim、gcc、make/makefile等;已经能够在
linux写代码,并且进行编译运行,让程序在linux下跑起来。
但是,如果我们在写代码的时候遇见了错误;但是我们并不知道错误在哪,在windows下,我们可以进行调试来查找代码错误的位置进行修改;我们在linux就只能查看源代码,直接查找错误,这样很麻烦;
现在就来学习linux如何调试程序。
调试程序 ——gdb/cgdb
Debug/Release模式
在之前学习C语言时,听说过Debug和Release,只知道Debug时用来调试的,程序员写代码的版本;而Release是发布版本。
现在我们来看一下这两个模式有什么区别
- 首先的区别就是
Debug会生成程序的调试信息,而Release不会生成程序的调试信息。
因为Debug模式会生成调试信息,所以Debug模式的程序就要比Release模式的程序大小要大。
我们如何验证呢?
linux中 gcc编译默认生成的是Release版本,我们要生成Debug模式就要带-g选项。
现在有这样一段代码test.c文件
#include<stdio.h>
int func(int n)
{int ret = 0;for (int i = 1; i <= n; i++){ret += i;}return n;
}
int main()
{int n = 100;int sum = func(n);printf("sum = %d\n", sum);return 0;
}
我们在linux下进行编译

这里有这样的提示,那是因为C98不支持在for循环中定义变量,要使用C99,上面也有提示。
所以我们就要这样来编译
gcc test.c -o test -st=c99
这里写成makefile方便操作。
这样生成的是Release模式的程序,我们查看它文件属性

现在,我们使用-g选项生成Debug模式的程序

可以看到Debug模式的要比Release模式的程序要大一些。
gdb/cgdb的使用
这里,只有Debug模式的程序才能被调试;Release模式下不能被调试,因为缺少调试信息。
在使用之前可能需要进行安装
yum -install -y gdb
yum -install -y cgdb
1. 进入调试
gdb 可执行程序
这里无论是gdb还是cgdb,都是可执行程序,对可执行程序进行调试。

可以看到这样就进入gdb调试了,但是gdb调试现在看不到我们的源代码。
2. 退出调试
quit

现在来看一下cgdb调试的界面
cgdb test

这样的界面看起来要比gdb好用一些,所以这里就以cgdb为例,来学习调试
cgdb中,屏幕上半部分可以看到一部分代码;其中绿色箭头指向的地方就是当前程序运行的位置。
退出调试仍然是quit
3. 查看代码
查看代码,l;后可以什么的不跟,也可以跟行号或者函数名
l:查看源代码,从上次位置开始,依次显示10行代码l 文件名:行号:列出指定文件的源代码l 函数名:列出指定函数的源代码

l 文件名:行号

l:函数名

这里列出的可能有一些差别。
4. 运行代码
我们进入调试,但是代码并没有运行起来;在windows下我们之间F5就让代码运行起来了;而cgdb中r命令可以让代码运行起来
r/run,执行代码:

逐步执行
有了断点,我们在
r时程序就会停止在断点处,那我们该如何一行一行执行代码呢?在
windows下,我们是按F10和F11来依次执行代码;在
linux中cgdb,我们使用n/next和s/step来依次执行代码
n/next,相当于F10,一行一行执行代码, 在遇到函数时,不进入函数内部;
s/step,就相当于F11,一行一行执行代码, 在遇到函数时,进入函数内部;
这里就不演示了。
执行到某处
在我们调试程序时,程序现在停止在一个断点处,我们不想一行一行执行代码,而是想要让程序直接运行到下一个代码;
只需要指向
c/contine即可
c/continue

r 重新执行
如果现在程序正在执行,我们想要让程序重新执行,只需要
r即可;这是会询问我们是否重新执行,
y即可

finish
执行到当前函数结束,然后停止

until 执行到某一行
until 行号程序执行到某一行然后停止。

现在执行until 11,让程序执行到11行。

5. 断点
增加/删除断点
我们指向
run/r后,发现代码直接就执行结束了;但是在我们调试的时候,我们并不希望代码执行运行结束,我们需要通过断点让代码在指定位置停下来;
在windows下,我们通过快捷键F9或者鼠标点击来打断点和去掉断点;
在cgdb中,我们通过命令**b/break**来打断点,通过delete/d来取消断点。
b打断点
b 行号:在指定行打断点b 函数名:在函数开头打断点

可以看到,我们打断点之后并看不到任何断点信息,那如果我们想要看到已经存在的断点,可以使用命令
info b来查看
info b查看所有断点信息

d删除断点
我们打断点可以通过
行号,但是删除断点我们就不能使用行号了,而是使用Num断点编号。

这里还要注意一个点,断点编号时不断递增的,不会随着我们删除断点而减小
什么意思呢,就是现在存在两个断点我们删除了其中一个断点,然后再次创建了一个断点,它的编号就是3而不是2。

这样有了断点,我们在执行
r时就程序就会停止在断点处。

这里看一下上半代码部分,可以看到程序停在了
15行,并且断点位置的行号颜色为红色。
启用/禁用断点
当我们在调试程序时,我们增加的断点并不一定所有的都能用的到,有一些断点我们不想让它在这次调试中起作用,这时就可以禁用这个断点
看到这里可能有疑惑,为什么不直接删除呢?
如果代码非常的多,删除了之后,接下来调试要用到,又要重新去找,非常浪费时间。
启用断点
enable 断点编号
禁用断点
disable 断点编号
这里断点默认是启用状态的。

那现在执行一下看是否真的禁用了呢?

可以看到第一个断点并未触发,而是直接触发第二个断点。
6. 监视
在windows下我们通过监视窗口来查看一个变量的值;
而在linux的cgdb中,我们也可以通过指令来查看变量的值。
监视变量
p
p用来查看一个变量当前的值

但是这样,我们在此执行代码会发现,执行过后就不在显示了;
这样我们每次查看就要去输入指令
p 变量名,这样好麻烦,我们想要每一次执行过后,它都会显示出来变量的值
display用来跟踪显示变量的值。
display

如上图所示,我们每一次执行代码,变量的值都会显示出来。
监视函数栈帧内局部变量
如果我们不是想要查看某一个变量,而是查看当前函数内所有的局部变量?
我们就要用到info/i locals

可以看到func中所有的局部变量都显示出来了。
查看当前函数调用栈帧
如果我们想要查看当前的函数调用栈帧,直接使用
bt/backtrace即可。

cgdb常用小技巧
1. watch
watch:用来监视一个变量的值是否发生变化,发生变化时会提示。
我们使用info b查看断点中也可以看到watch监视的变量。
2. set war
set war:在调试过程中,修改变量的值。

可以看到,我们在调试过程中,使用set var就可以修改一个变量的值。
3. 条件断点
添加条件断点
b 行号 if 条件

如上图所示,新添加的条件断点(当i==10时触发)。

可以看到程序在i==0时,断点触发,停止在第九行。
给已存在断点增加条件
当我们需要给已经存在的断点增加条件时,我们需要指令
condition 断点编号 条件

到这里本篇内容就结束了,希望对你有所帮助。
制作不易,感谢大佬的支持。
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws
相关文章:
深入了解Linux —— 调试程序
前言 我们已经学习了linux下许多的工具,vim、gcc、make/makefile等; 已经能够在linux写代码,并且进行编译运行,让程序在linux下跑起来。 但是,如果我们在写代码的时候遇见了错误;但是我们并不知道错误在哪&…...
Hive-优化(语法优化篇)
列裁剪与分区裁剪 在生产环境中,会面临列很多或者数据量很大时,如果使用select * 或者不指定分区进行全列或者全表扫描时效率很低。Hive在读取数据时,可以只读取查询中所需要的列,忽视其他的列,这样做可以节省读取开销…...
物联网(Internet of Things, IoT)中的网络层简介
物联网(Internet of Things, IoT)中的网络层是物联网架构中的关键组成部分,负责设备之间的数据传输和通信。网络层的主要任务是将感知层(传感器、设备等)收集到的数据通过互联网或其他通信网络传输到应用层(数据处理和分析平台)。以下是物联网网络层的知识简介: 1. 物联…...
C++ 提供了多种数据类型组合方式
C 提供了多种数据类型组合方式,允许开发者将基本类型组合成更复杂的数据结构,以满足不同场景的需求。以下是主要的组合方式及其示例: 1. 数组(Array) 同类型元素的集合,可以是静态或动态。 int staticArr…...
八字排盘宝 2025.1.8 | 多模式排盘工具,精准解析八字信息,轻量易用
八字排盘宝是一款轻量高效的排盘工具,实现多模式排盘功能,界面简洁易用,适合命理爱好者和专业人士。支持多种排盘方式,精准解析八字信息,提供快速、便捷的命理分析体验,是日常排盘和命理学习的得力助手。 …...
MySQL面试篇——性能优化
MySQL性能优化 在MySQL中,如何定位慢查询 慢查询表象:页面加载过慢、接口压测响应时间过长(超过1s)。造成慢查询的原因通常有:聚合查询、多表查询、表数据量过大查询、深度分页查询 方案一:开源工具 调试工…...
c#财务软件专业版企业会计做账软件财务管理系统软件
本软件为绍兴客户开发的仿某碟财务软件专业版 功能:可以按会计科目做账录入会计凭证、结转损益、期末结账、拉资产负债表 github下载:https://github.com/oyangxizhe/financial.git...
常见 JVM 工具介绍
1. jps(Java Virtual Machine Process Status Tool) 功能:列出当前用户的所有 Java 进程及其 PID。 常用场景:快速定位目标 Java 应用的进程 ID。 常用命令: bash复制 jps -l # 显示主类全名 jps -v # 显示 JVM 启…...
【含文档+PPT+源码】Python爬虫人口老龄化大数据分析平台的设计与实现
项目介绍 本课程演示的是一款Python爬虫人口老龄化大数据分析平台的设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Python学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本…...
生成对抗网络(GAN)原理与应用
目录 一、引言 二、GAN的基本原理 (一)生成器(Generator)的工作机制 (二)判别器(Discriminator)的工作机制 (三)对抗训练的过程 三、GAN在AIGC生图中的应…...
Linux安装升级docker
Linux 安装升级docker Linux 安装升级docker背景升级停止docker服务备份原docker数据目录移除旧版本docker安装docker ce恢复数据目录启动docker参考 安装找到docker官网找到docker文档删除旧版本docker配置docker yum源参考官网继续安装docker设置开机自启配置加速测试 Linux …...
clickhouse源码分析
《ClickHouse源码分析》 当我们谈论数据库时,ClickHouse是一个不容忽视的名字。它是一个用于联机分析处理(OLAP)的列式数据库管理系统(DBMS),以其快速的数据查询能力而闻名。对于想要深入了解这个高效工具…...
IDEA 基础配置: maven配置 | 服务窗口配置
文章目录 IDEA版本与MAVEN版本对应关系maven配置镜像源插件idea打开服务工具窗口IDEA中的一些常见问题及其解决方案IDEA版本与MAVEN版本对应关系 查找发布时间在IDEA版本之前的dea2021可以使用maven3.8以及以前的版本 比如我是idea2021.2.2 ,需要将 maven 退到 apache-maven-3.…...
【redis】type命令和定时器的两种实现方式(优先级队列、时间轮)
type——返回 key 对应的数据类型 此处 Redis 所有的 key 都是 string,但是 key 对应的 value 可能会存在多种类型 none —— key 不存在string ——字符串list ——列表set ——集合zset ——有序集合hash ——哈希表stream ——Redis 作为消息队列的时候&#x…...
高并发下订单库存防止超卖策略
文章目录 什么是超卖问题?推荐策略:Redis原子操作(Redis incr)乐观锁lua脚本利用Redis increment 的原子操作,保证库存数安全update使用乐观锁LUA脚本保持库存原子性 什么是超卖问题? 在并发的场景下,比如商城售卖商品…...
task01
1:大模型能够专业的回答各种问题,并且擅长文本处理,代码编写,可以减少一部分人类的工作。 本节学习了大模型提示词的三要素,角色,背景,输出样式,在kimi上我复现了教材的任务…...
【Kotlin】Kotlin基础笔记
一、数据类型 1.1 变量声明与类型推导 变量声明 使用 val 声明不可变变量(相当于常量);使用 var 声明可变变量。 val a 10 // 类型自动推断为 Int,不可变 var b: Double 5.0 // 显示声明为 Double,可变变量…...
DeepSeek教我写词典爬虫获取单词的音标和拼写
Python在爬虫领域展现出了卓越的功能性,不仅能够高效地抓取目标数据,还能便捷地将数据存储至本地。在众多Python爬虫应用中,词典数据的爬取尤为常见。接下来,我们将以dict.cn为例,详细演示如何编写一个用于爬取词典数据…...
祛魅 Manus ,从 0 到 1 开源实现
背景介绍 Manus 是最近一个现象级的大模型 Agent 工具,自从发布以来,被传出各种神乎其神的故事,自媒体又开始炒作人类大量失业的鬼故事,Manus 体验码也被炒作为 10w 的高价。 之后又出现反转,被爆出实际体验效果不佳…...
C++入门——输入输出、缺省参数
C入门——输入输出、缺省参数 一、C标准库——命名空间 std C标准库std是一个命名空间,全称为"standard",其中包括标准模板库(STL),输入输出系统,文件系统库,智能指针与内存管理&am…...
Spring Boot应用开发:从零到生产级实战指南
Spring Boot应用开发:从零到生产级实战指南 Spring Boot应用开发:从零到生产级实战指南一、Spring Boot的核心价值二、快速构建第一个Spring Boot应用2.1 使用Spring Initializr初始化项目2.2 项目结构解析2.3 编写第一个REST接口 三、Spring Boot的核心…...
【2025前端高频面试题——系列一之MVC和MVVM】
前端高频面试题——系列一之MVC和MVVM 前言一、MVC的基本逻辑二、MVVM的基本逻辑总结 提示:片尾总结了要点,硬背的话直接跳到最后 前言 相信持续关注我文章的小伙伴知道我之前就MVC和MVVM做过较为详细的讲解,但是我发现,他依旧是…...
基于遗传算法的IEEE33节点配电网重构程序
一、配电网重构原理 配电网重构(Distribution Network Reconfiguration, DNR)是一项优化操作,旨在通过改变配电网中的开关状态,优化电力系统的运行状态,以达到降低网损、均衡负载、改善电压质量等目标。配电网重构的核…...
HTTP协议与Web开发
🌐 HTTP协议与Web开发完全指南:从原理到实战 一、HTTP协议是什么? HTTP(超文本传输协议) 是互联网上应用最广泛的网络协议,作为Web开发的基石,它具有以下核心特性: 无状态协议&am…...
容器编排革命:从 Docker Run 到 Docker Compose 的进化之路20250309
容器编排革命:从 Docker Run 到 Docker Compose 的进化之路 一、容器化部署的范式转变 在 Docker 生态系统的演进中,容器编排正从“手动操作”走向“自动化管理”。根据 Docker 官方 2023 年开发者调查报告,78% 的开发者已采用 Docker Compo…...
【高并发内存池】释放内存 + 申请和释放总结
高并发内存池 1. 释放内存1.1 thread cache1.2 central cache1.3 page cache 2. 申请和释放剩余补充 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励,我们一起努力吧!😃&#x…...
自然语言处理:最大期望值算法
介绍 大家好,博主又来给大家分享知识了,今天给大家分享的内容是自然语言处理中的最大期望值算法。那么什么是最大期望值算法呢? 最大期望值算法,英文简称为EM算法,它的核心思想非常巧妙。它把求解模型参数的过程分成…...
Python绘制数据分析中经典的图形--列线图
Python绘制数据分析中经典的图形–列线图 列线图是数据分析中的经典图形,通过背后精妙的算法设计,展示线性模型(logistic regression 和Cox)中各个变量对于预测结果的总体贡献(线段长短),另外&…...
11. 盛最多水的容器(力扣)
11. 盛最多水的容器 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明:你不…...
vue3 vite或者vue2 百度地图(卫星图)离线使用详细讲解
1、在Windows上下载瓦片,使用的工具为: 全能电子地图下载器3.0最新版(推荐) 下载后解压,然后进入目录"全能电子地图下载器3.0最新版(推荐)\全能电子地图下载器3.0\MapTileDownloader" 在这个目录…...

