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

调试工具之GDB的基本使用

GDB基本使用

GDB是Linux下一款非常强大的调试软件,其实就是GNU Debugger的缩写。接下来我们学习一下他的基本使用。
例子函数,其中只有一个ds18b20的采集温度函数和一个主函数:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>int measure_temp(float *temp);int main(int argc,char *argv[])
{float 				   temp = 0;measure_temp(&temp);printf("the temp:%f\n",temp);return 0;
}int measure_temp(float *temp)
{int					   fd = -1;//打开ds18b20时候的文件描述符int					   found = -1;//是否找到chip的参数。char            	   *w1_path = "/sys/bus/w1/devices/"; //文件名的前半段,28-后面不能确定,因为设备号会变化,我们一会获取。char				   chip[32];//文件名的后半段,-28char				   ds_path[128];//拼凑出全部的路径名DIR					   *dirp = NULL;//打开w1时返回的DIR类型文件指针struct dirent          *direntp = NULL;//是readdir后返回的文件夹信息结构体指针char				   buf[1024];char 				   *ptr;//用来指向温度值if (NULL == temp){printf("mesure_temp arguments error:[%s]\n",strerror(errno));return -1;}printf("measure_temp arguments right!\n");//打开devices文件夹if ( NULL == (dirp = opendir(w1_path)) ){printf("open w1_path error:[%s]\n",strerror(errno));return -2;}printf("open w1_path DIR[%p] success!\n",dirp);//readdir查找这个文件夹下有什么while(NULL != (direntp=readdir(dirp))){if (strstr(direntp->d_name,"28-")){strncpy(chip,direntp->d_name,sizeof(chip));//duancuowufound = 1;}}closedir(dirp);if (found < 0){printf("nofind \"-28\" \n");return -3;}printf("find chip success[%s]\n",chip);snprintf(ds_path,sizeof(ds_path),"%s%s/w1_slave",w1_path,chip);printf("ds_path:%s\n",ds_path);if ((fd = open(ds_path,O_RDONLY)) < 0){printf("open error[%s]\n",strerror(errno));return -4;}int i;int *p = NULL;p = &i;//read fd memset(buf,0,sizeof(buf));if ( read(fd,buf,sizeof(buf)) <=0 ){printf("error:[%s]\n",strerror(errno));return -5;}//printf("temperature:[%s]\n",buf);if ( NULL == (ptr = strstr(buf,"t=") )){printf("nofound error[%s]\n",strerror(errno));return -6;}//printf("%s\n",ptr);ptr += 2;*temp = atof(ptr)/1000;return 0;
}

(1)首先我们使用 gcc 直接生成的程序是没有调试信息的,所以我们要使用 gcc -g 命令来生成一个带有调试信息版本的目标文件。

在这里插入图片描述

(2)然后我们用 gdb 来打开这个目标文件,其实就是让带有调试信息的二进制文件在我们 gdb 的这个 “盒子” 里面进行运行。 用 gdb + 目标文件 命令来运行它。

在这里插入图片描述

(3)之后我们就可以开始调试啦!如何让 test_gdb.o 这个文件在gdb中跑起来呢?在 gdb 中输入 run 就可以了。

在这里插入图片描述

(4)不过我们发现,这和不使用 gdb 跑程序没有什么区别,所以我们学习如何增加断点。

增加断点是通过 break 命令来实现的,他有三种基本的使用形式,如下:

(gdb) break main               	# 在 main 函数处设置断点
(gdb) break my_program.c:10    	# 在 my_program.c 文件的第 10 行设置断点
(gdb) break my_function        	# 在 my_function 函数处设置断点

(5)这里假设我们程序异常退出了,但我们不清楚导致退出的错误是发生在 measure 测温函数内还是函数之前,我们就可以在进入这个函数之前,设置一个断点,然后运行它。
在这里插入图片描述我们可以看到,程序成功运行到了这个函数前,没有抛出异常,那么我们就可以确定,异常是在 measure 测温函数内的了。

(6)使用 next 单步执行,但是不进入到函数内部。

在这里插入图片描述

(7)也可以使用step单步执行,但是会进入到函数内部。

在这里插入图片描述

(8)使用bt命令或者backtrace命令显示调用的栈信息:

在这里插入图片描述

(9)显示所有的断点:

在这里插入图片描述

(10)删除特定的某一个断点:

在这里插入图片描述

运行到某一个断点后,要直接运行到下一个断点,使用continue 或者 c 就可以了。若后面没有断点了,那么就会一直运行到结束或者某个循环里面。

命令汇总:

(gdb) break main               	# 在 main 函数处设置断点
(gdb) break my_program.c:10    	# 在 my_program.c 文件的第 10 行设置断点
(gdb) break my_function        	# 在 my_function 函数处设置断点(gdb) next                     # 或 (gdb) n 单步执行,不进入函数内部
(gdb) step                     # 或 (gdb) s 单步执行,进入函数内部
(gdb) finish                   # 运行到当前函数返回的位置
(gdb) until                    # 运行到循环结束的位置(gdb) run                      # 启动程序
(gdb) continue                 # 或 (gdb) c 继续运行直到下一个断点(gdb) backtrace                # 或 (gdb) bt 显示调用栈
(gdb) frame n                  # 切换到调用栈中的第 n 帧
(gdb) info frame               # 显示当前帧的信息
(gdb) info locals              # 显示当前帧的局部变量(gdb) info breakpoints         # 或 (gdb) info b 显示所有断点
(gdb) delete breakpoint_number # 或 (gdb) d breakpoint_number 删除特定断点
(gdb) clear                    # 删除当前行的断点
(gdb) disable breakpoint_number# 禁用特定断点
(gdb) enable breakpoint_number # 启用特定断点

当然,我们也可以在运行过程中对某些变量进行查看和修改:
在这里插入图片描述

这里用到的命令是:

print 变量名  			#打印变量的值,注意,没有print,没有f。
set var 变量 =# 改变某个变量的值

相关文章:

调试工具之GDB的基本使用

GDB基本使用 GDB是Linux下一款非常强大的调试软件&#xff0c;其实就是GNU Debugger的缩写。接下来我们学习一下他的基本使用。 例子函数&#xff0c;其中只有一个ds18b20的采集温度函数和一个主函数&#xff1a; #include <stdio.h> #include <errno.h> #includ…...

C++ //练习 16.14 编写Screen类模板,用非类型参数定义Screen的高和宽。

C Primer&#xff08;第5版&#xff09; 练习 16.14 练习 16.14 编写Screen类模板&#xff0c;用非类型参数定义Screen的高和宽。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 template <int H, int W> class Screen{…...

【Java】深度解析监视器的组成原理

目录 一、什么是监视器&#xff08;Monitor&#xff09;二、监视器的组成部分三、线程的状态转换四、总结 一、什么是监视器&#xff08;Monitor&#xff09; 在Java中&#xff0c;监视器&#xff08;Monitor&#xff09;是用来实现线程同步的一种机制。每个Java对象都有一个与…...

Day14-Servlet后端验证码的实现

图片验证码的生成采用的是Kaptcha&#xff1b; Kaptcha是一个高度可配置的验证码生成工具&#xff0c;由Google开源。它通过一系列配置文件和插件&#xff0c;实现了将验证码字符串自动转换成图片流&#xff0c;并可以与session进行关联&#xff0c;从而在验证过程中使用&#…...

MySQL:数据库权限与角色

权限 MySQL 的权限管理系统是保障数据库安全性的关键组件之一。它允许数据库管理员精确控制哪些用户可以对哪些数据库对象执行哪些操作。 自主存取控制 DAC&#xff08;DiscretionaryAccess Control)&#xff1a;用户对于不同的数据库对象有不同的存取权限&#xff0c;不同的…...

等保测评练习卷25

等级保护初级测评师试题25 姓名&#xff1a; 成绩&#xff1a; 一、判断题&#xff08;10110分&#xff09; 1.安全区域边界对象主要根据系统中网络访问控制设备的部署情况来确定&#xff08;&#xff09;不是网络访问控制设备而…...

《python语言程序设计》2018第6章第28题 掷骰子 两个色子,分别是1到6

2、3、12 玩家输 7、11玩家赢 4、5、6、8、9、10算1点&#xff0c;之后出7玩家输或者和上一次相同。def rolled(num_t):count 0still_win 0second_win 0still_lose 0second_lose 0while count < num_t:a_1 random.randint(1, 6)b_1 random.randint(1, 6)tTen a_1 b…...

Java方法递归

目录 1.方法递归调用 基本介绍 递归能解决什么问题&#xff1f; 八皇后问题 递归举例 递归重要规则 练习 2.递归调用应用实例-迷宫问题 3.递归调用实例-汉诺塔 4.递归调用实例-八皇后问题 1.方法递归调用 基本介绍 简单来说&#xff0c;递归就是自己调用自己。 …...

目标跟踪那些事

目标跟踪那些事 跟踪与检测的区别 目标跟踪和目标检测是计算机视觉中的两个重要概念&#xff0c;但它们的目的和方法是不同的。 目标检测(object Detection)&#xff1a;是指在图像或视频帧中识别并定位一个或多个感兴趣的目标对象的过程 。 目标跟踪(object Tracking)&…...

【Git】 如何将一个分支的某个提交合并到另一个分支

【Git】 如何将一个分支的某个提交合并到另一个分支 在使用 Git 进行版本控制时&#xff0c;常常会遇到这样的需求&#xff1a;将某个分支的特定提交合并到另一个分支中。这种情况下&#xff0c;我们可以使用 cherry-pick 命令来实现。本文将详细介绍 cherry-pick 命令的使用方…...

【嵌入式之RTOS】什么是消息队列

目录 一、FreeRTOS消息队列的基本概念 二、FreeRTOS消息队列的工作原理 三、FreeRTOS消息队列的特点 四、FreeRTOS消息队列的应用 五、示例 消息队列是一种用于任务间通信的机制&#xff0c;它允许一个任务&#xff08;生产者&#xff09;向消息队列发送消息&#xff0c;而…...

9-springCloud集成nacos config

本文介绍spring cloud集成nacos config的过程。 0、环境 jdk 1.8maven 3.8.1Idea 2021.1nacos 2.0.3 1、项目结构 根项目nacos-config-sample下有两个module&#xff0c;这两个module分别是两个springboot项目&#xff0c;都从nacos中获取连接mysql的连接参数。我们开工。 …...

市场主流 AI 视频生成技术的迭代路径

AI视频生成技术的迭代路径经历了从GANVAE、Transformer、Diffusion Model到Sora采用的DiT架构&#xff08;TransformerDiffusion&#xff09;等多个阶段&#xff0c;每个阶段的技术升级都在视频处理质量上带来了飞跃性的提升。这些技术进步不仅推动了AI视频生成领域的快速发展&…...

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——1.c++入门(2)

1. 函数重载 C⽀持在同⼀作⽤域中出现同名函数&#xff0c;但是要求这些同名函数的形参不同&#xff0c;可以是参数个数不同或者 类型不同。这样C函数调⽤就表现出了多态⾏为&#xff0c;使⽤更灵活。C语⾔是不⽀持同⼀作⽤域中出现同 名函数的。 #include<iostream> u…...

【Python系列】深入理解 Python 中的 `nonlocal` 关键字

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

Flask目录结构路由重定向简单实例讲解——轻量级的 Python Web 框架

假设一个flask目录结构如下&#xff1a; my_flask_app/ │ ├── app.py ├── routes/ │ ├── __init__.py │ ├── ZhejiangProvince/ │ │ ├── __init__.py │ │ ├── la.py │ │ └── el.py │ ├── GuangdongProvince/ │ │ ├…...

破解PyCharm插件更新难题:让IDE焕发新生

破解PyCharm插件更新难题&#xff1a;让IDE焕发新生 PyCharm作为业界领先的集成开发环境&#xff08;IDE&#xff09;&#xff0c;其丰富的插件生态是其强大功能的重要来源。然而&#xff0c;插件无法更新的问题可能会困扰许多用户&#xff0c;影响开发体验。本文将详细介绍如…...

cmake常用命令学习

1.include https://blog.csdn.net/qq_38410730/article/details/102677143 CmakeLists.txt才是cmake的正统文件&#xff0c;而.cmake文件是一个模块文件&#xff0c;可以被include到CMakeLists.txt中。 include指令一般用于语句的复用&#xff0c;也就是说&#xff0c;如果有…...

K8S可视化管理平台KubeSphere

什么是 KubeSphere &#xff1f; KubeSphere 是一款开源项目&#xff0c;在目前主流容器调度平台 Kubernetes 之上构建的企业级分布式多租户容器管理平台&#xff0c;提供简单易用的操作界面以及向导式操作方式&#xff0c;在降低用户使用容器调度平台学习成本的同时&#xff…...

Bugku-CTF-聪明的php

pass a parameter and maybe the flag files filename is random :> 传递一个参数&#xff0c;可能标记文件的文件名是随机的: 于是传一下参&#xff0c;在原网页后面加上/?a1,发现网页出现了变化 3.传入参数&#xff0c;一般情况下是文件包含&#xff0c;或者命令执行&…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...