深入了解Linux —— 调试程序

news2025/4/21 20:38:23

前言

我们已经学习了linux下许多的工具,vimgccmake/makefile等;

已经能够在linux写代码,并且进行编译运行,让程序在linux下跑起来。

但是,如果我们在写代码的时候遇见了错误;但是我们并不知道错误在哪,在windows下,我们可以进行调试来查找代码错误的位置进行修改;我们在linux就只能查看源代码,直接查找错误,这样很麻烦;

现在就来学习linux如何调试程序。

调试程序 ——gdb/cgdb

Debug/Release模式

在之前学习C语言时,听说过DebugRelease,只知道Debug时用来调试的,程序员写代码的版本;而Release是发布版本。

现在我们来看一下这两个模式有什么区别

  • 首先的区别就是Debug会生成程序的调试信息,而Release不会生成程序的调试信息。

因为Debug模式会生成调试信息,所以Debug模式的程序就要比Release模式的程序大小要大。

我们如何验证呢?

linuxgcc编译默认生成的是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就让代码运行起来了;而cgdbr命令可以让代码运行起来

r/run,执行代码:

在这里插入图片描述

逐步执行

有了断点,我们在r时程序就会停止在断点处,那我们该如何一行一行执行代码呢?

windows下,我们是按F10F11来依次执行代码;

linuxcgdb,我们使用n/nexts/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下我们通过监视窗口来查看一个变量的值;

而在linuxcgdb中,我们也可以通过指令来查看变量的值。

监视变量

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

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

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

相关文章

Hive-优化(语法优化篇)

列裁剪与分区裁剪 在生产环境中&#xff0c;会面临列很多或者数据量很大时&#xff0c;如果使用select * 或者不指定分区进行全列或者全表扫描时效率很低。Hive在读取数据时&#xff0c;可以只读取查询中所需要的列&#xff0c;忽视其他的列&#xff0c;这样做可以节省读取开销…

八字排盘宝 2025.1.8 | 多模式排盘工具,精准解析八字信息,轻量易用

八字排盘宝是一款轻量高效的排盘工具&#xff0c;实现多模式排盘功能&#xff0c;界面简洁易用&#xff0c;适合命理爱好者和专业人士。支持多种排盘方式&#xff0c;精准解析八字信息&#xff0c;提供快速、便捷的命理分析体验&#xff0c;是日常排盘和命理学习的得力助手。 …

MySQL面试篇——性能优化

MySQL性能优化 在MySQL中&#xff0c;如何定位慢查询 慢查询表象&#xff1a;页面加载过慢、接口压测响应时间过长&#xff08;超过1s&#xff09;。造成慢查询的原因通常有&#xff1a;聚合查询、多表查询、表数据量过大查询、深度分页查询 方案一&#xff1a;开源工具 调试工…

c#财务软件专业版企业会计做账软件财务管理系统软件

本软件为绍兴客户开发的仿某碟财务软件专业版 功能&#xff1a;可以按会计科目做账录入会计凭证、结转损益、期末结账、拉资产负债表 github下载&#xff1a;https://github.com/oyangxizhe/financial.git

【含文档+PPT+源码】Python爬虫人口老龄化大数据分析平台的设计与实现

项目介绍 本课程演示的是一款Python爬虫人口老龄化大数据分析平台的设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Python学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本…

生成对抗网络(GAN)原理与应用

目录 一、引言 二、GAN的基本原理 &#xff08;一&#xff09;生成器&#xff08;Generator&#xff09;的工作机制 &#xff08;二&#xff09;判别器&#xff08;Discriminator&#xff09;的工作机制 &#xff08;三&#xff09;对抗训练的过程 三、GAN在AIGC生图中的应…

Linux安装升级docker

Linux 安装升级docker Linux 安装升级docker背景升级停止docker服务备份原docker数据目录移除旧版本docker安装docker ce恢复数据目录启动docker参考 安装找到docker官网找到docker文档删除旧版本docker配置docker yum源参考官网继续安装docker设置开机自启配置加速测试 Linux …

clickhouse源码分析

《ClickHouse源码分析》 当我们谈论数据库时&#xff0c;ClickHouse是一个不容忽视的名字。它是一个用于联机分析处理&#xff08;OLAP&#xff09;的列式数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;以其快速的数据查询能力而闻名。对于想要深入了解这个高效工具…

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&#xff0c;但是 key 对应的 value 可能会存在多种类型 none —— key 不存在string ——字符串list ——列表set ——集合zset ——有序集合hash ——哈希表stream ——Redis 作为消息队列的时候&#x…

task01

1&#xff1a;大模型能够专业的回答各种问题&#xff0c;并且擅长文本处理&#xff0c;代码编写&#xff0c;可以减少一部分人类的工作。 本节学习了大模型提示词的三要素&#xff0c;角色&#xff0c;背景&#xff0c;输出样式&#xff0c;在kimi上我复现了教材的任务&#xf…

DeepSeek教我写词典爬虫获取单词的音标和拼写

Python在爬虫领域展现出了卓越的功能性&#xff0c;不仅能够高效地抓取目标数据&#xff0c;还能便捷地将数据存储至本地。在众多Python爬虫应用中&#xff0c;词典数据的爬取尤为常见。接下来&#xff0c;我们将以dict.cn为例&#xff0c;详细演示如何编写一个用于爬取词典数据…

祛魅 Manus ,从 0 到 1 开源实现

背景介绍 Manus 是最近一个现象级的大模型 Agent 工具&#xff0c;自从发布以来&#xff0c;被传出各种神乎其神的故事&#xff0c;自媒体又开始炒作人类大量失业的鬼故事&#xff0c;Manus 体验码也被炒作为 10w 的高价。 之后又出现反转&#xff0c;被爆出实际体验效果不佳…

C++入门——输入输出、缺省参数

C入门——输入输出、缺省参数 一、C标准库——命名空间 std C标准库std是一个命名空间&#xff0c;全称为"standard"&#xff0c;其中包括标准模板库&#xff08;STL&#xff09;&#xff0c;输入输出系统&#xff0c;文件系统库&#xff0c;智能指针与内存管理&am…

Spring Boot应用开发:从零到生产级实战指南

Spring Boot应用开发&#xff1a;从零到生产级实战指南 Spring Boot应用开发&#xff1a;从零到生产级实战指南一、Spring Boot的核心价值二、快速构建第一个Spring Boot应用2.1 使用Spring Initializr初始化项目2.2 项目结构解析2.3 编写第一个REST接口 三、Spring Boot的核心…

【2025前端高频面试题——系列一之MVC和MVVM】

前端高频面试题——系列一之MVC和MVVM 前言一、MVC的基本逻辑二、MVVM的基本逻辑总结 提示&#xff1a;片尾总结了要点&#xff0c;硬背的话直接跳到最后 前言 相信持续关注我文章的小伙伴知道我之前就MVC和MVVM做过较为详细的讲解&#xff0c;但是我发现&#xff0c;他依旧是…

基于遗传算法的IEEE33节点配电网重构程序

一、配电网重构原理 配电网重构&#xff08;Distribution Network Reconfiguration, DNR&#xff09;是一项优化操作&#xff0c;旨在通过改变配电网中的开关状态&#xff0c;优化电力系统的运行状态&#xff0c;以达到降低网损、均衡负载、改善电压质量等目标。配电网重构的核…

容器编排革命:从 Docker Run 到 Docker Compose 的进化之路20250309

容器编排革命&#xff1a;从 Docker Run 到 Docker Compose 的进化之路 一、容器化部署的范式转变 在 Docker 生态系统的演进中&#xff0c;容器编排正从“手动操作”走向“自动化管理”。根据 Docker 官方 2023 年开发者调查报告&#xff0c;78% 的开发者已采用 Docker Compo…

【高并发内存池】释放内存 + 申请和释放总结

高并发内存池 1. 释放内存1.1 thread cache1.2 central cache1.3 page cache 2. 申请和释放剩余补充 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x…

自然语言处理:最大期望值算法

介绍 大家好&#xff0c;博主又来给大家分享知识了&#xff0c;今天给大家分享的内容是自然语言处理中的最大期望值算法。那么什么是最大期望值算法呢&#xff1f; 最大期望值算法&#xff0c;英文简称为EM算法&#xff0c;它的核心思想非常巧妙。它把求解模型参数的过程分成…