深入了解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下跑起来。 但是,如果我们在写代码的时候遇见了错误;但是我们并不知道错误在哪&…...

JVM - 3.垃圾回收
1.垃圾收集的经典问题 1.哪些内存需要回收2.什么时候回收3.如何回收1.你知道哪几种垃圾回收器,各自的优缺点,重点讲一下cms和g12.JVM GC算法有哪些,目前的JDK版本采用什么回收算法3.G1回收器的回收过程 1.Java中垃圾的定义(Garbag…...
vs code 设置字体颜色
修改setting.json文件 {"remote.SSH.remotePlatform": {"ubuntu": "linux"},// "workbench.colorTheme": "One Dark Pro",// "editor.semanticTokenColorCustomizations": {// },"editor.semanticTokenColo…...
MoonSharp 文档一
目录 1.Getting Started(入门手册) 步骤1:在 IDE 中引入 MoonSharp 步骤2:引入命名空间 步骤3:调用脚本 步骤4:运行代码 2.Keeping a Script around(保留一个脚本) 步骤1:复现前教程所有操作 步骤2:改为创建Script对象 步骤3:访问全局环境 步骤4:直接调用…...
Unity3D 图形渲染(Graphics Rendering)详解
前言 Unity3D 是一款广泛使用的游戏引擎,其图形渲染系统是开发者创建高质量视觉效果的核心。本文将深入探讨 Unity3D 的图形渲染管线、渲染技术、以及如何通过代码实现自定义渲染效果。 对惹,这里有一个游戏开发交流小组,大家可以点击进来一…...

计算机视觉图像点运算【灰度直方图均衡化图形界面实操理解 +开源代码】
对一个数字图像处理系统来说,一般的处理过程为三个步骤:图像预处理、特征抽取、图像识别和分析。图像的点运算就是预处理过程中的重要一步,点运算是对图像的灰度级进行变换。 图像点运算概念 点运算是指对图像的每个像素依次进行相同的灰度变…...

在Windows 7操作系统,基于llama.cpp本地化部署 deepseek-r1模型的方法 2025-02-08
一、概述 现在已经是大模型时代。 个人认为,deepseek效果惊艳,大模型已进入实用阶段。 有些电脑,由于种种原因,还在用 Windows 7, Windows XP 等操作系统。 为了让这些电脑用上大模型,本教程在 llama.c…...
力扣146 - LRU缓存
视频讲解 哈希 双向链表 为什么要用双向链表? 快速删除节点(O(1)) 如果是单链表的话,删除一个节点时,需要从头遍历,找到前驱节点,才能修改 prev->next,导致 O(n)…...
C++ 算法竞赛STL以及常见模板
目录 STL /*═══════════════ Vector ═══════════════*/ /*════════════════ Pair ════════════════*/ /*══════════════ String ════════════════*/ /*══════════…...
微信小程序将markdown内容转为pdf并下载
要在微信小程序中将Markdown内容转换为PDF并下载,您可以使用以下方法: 方法一:使用第三方API服务 选择第三方API服务: 可以选择像 Pandoc、Markdown-PDF 或 PDFShift 这样的服务,将Markdown转换为PDF。例如,PDFShift 提供了一个API接口,可以将Markdown内容转换为PDF格式…...

AI绘画软件Stable Diffusion详解教程(7):图生图基础篇(改变图像风格)
我们在使用AI魔盒不停的绘制一幅幅图像时,会有这样的疑问:为什么生成的图像随机性这么强?我们如何按照自己的构图创作作品?为什么提示词生成的图像细节不够?如何把手绘的风格转换成另一种风格,或者说把自己…...
ES映射知识
映射 映射类似于关系型数据库的Schema(模式)。 映射来定义字段列和存储的类型等基础信息。 {"mappings": {"properties": {"username": {"type": "keyword","ignore_above": 256 // 忽略…...

蓝桥杯嵌入式组第七届省赛题目解析+STM32G431RBT6实现源码
文章目录 1.题目解析1.1 分而治之,藕断丝连1.2 模块化思维导图1.3 模块解析1.3.1 KEY模块1.3.2 ADC模块1.3.3 IIC模块1.3.4 UART模块1.3.5 LCD模块1.3.6 LED模块1.3.7 TIM模块 2.源码3.第七届题目 前言:STM32G431RBT6实现嵌入式组第七届题目解析源码&…...

SpringBoot项目配置文件
SpringBoot项目提供了多种属性配置方式(properties、yaml、yml) yml配置文件 使用Apifox可以方便开发接口、前端测试等 工程搭建: 1.创建SpringBoot工程,并引入web开发起步依赖、mybatis、mysql驱动、lombok 2.创建数据库表&am…...

PythonWeb开发框架—Flask框架之flask-sqlalchemy、序列化和反序列化使用详解
1.安装依赖库 pip install flask-sqlalchemy pip install pymysql 2.连接数据库配置 from flask import Flask from flask_sqlalchemy import SQLAlchemyapp Flask(__name__) #创建 Flask 应用实例#配置数据库连接 app.config[SQLALCHEMY_DATABASE_URI]mysql://root:stud…...
如何监控 Pod 的 CPU/内存使用率,prometheus+grafana
一、监控 Pod 的 CPU/内存使用率的方法 1. 使用 kubectl top 命令(临时检查) # 查看所有 Pod 的资源使用率(需安装 Metrics Server) kubectl top pods --all-namespaces # 查看指定命名空间的 Pod kubectl top pods -n <n…...
Spring Batch 概览
Spring Batch 是什么? Spring Batch 是 Spring 生态系统中的一个轻量级批处理框架,专门用于处理大规模数据任务。它特别适合企业级应用中需要批量处理数据的场景,比如数据迁移、报表生成、ETL(Extract-Transform-Load)…...

用Deepseek写一个五子棋微信小程序
在当今快节奏的生活中,休闲小游戏成为了许多人放松心情的好选择。五子棋作为一款经典的策略游戏,不仅规则简单,还能锻炼思维。最近,我借助 DeepSeek 的帮助,开发了一款五子棋微信小程序。在这篇文章中,我将…...
AF3 squeeze_features函数解读
AlphaFold3 data_transforms 模块的 squeeze_features 函数的作用去除 蛋白质特征张量中不必要的单维度(singleton dimensions)和重复维度,以使其适配 AlphaFold3 预期的输入格式。 源代码: def squeeze_features(protein):&qu…...

Python 远程抓取服务器日志最后 1000行
哈喽,大家好,我是木头左! 一、神奇的 Python 工具箱 1. SSH 连接的密钥——paramiko paramiko 库提供了丰富的方法来处理 SSH 连接的各种细节。从创建连接对象,到执行远程命令,再到获取命令输出,它都能有…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...