掌握高效实用的VS调试技巧


1.编程常见的错误
1.1编译型错误
编程编译型错误是指在编译代码时发现的错误。编译器在编译过程中会检查代码是否符合语法规范和语义要求,如果发现错误会产生编译错误。
直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单。
如下图所示:

以下是一些常见的编译型错误:
-
语法错误:代码不符合编程语言的语法规范,常见的语法错误包括拼写错误、缺少分号、括号不匹配等。
-
类型错误:变量或表达式的数据类型不匹配,例如将字符串赋值给整数变量。
-
未声明的标识符:使用了未声明的变量、函数或类名。
-
重复定义:重复声明、定义了同名的变量、函数或类。
-
缺少头文件或引用错误:在C/C++程序中,使用了未包含的头文件或引用了未定义的标识符。
-
语义错误:代码逻辑不合理或不符合语义要求,例如使用了未初始化的变量、使用了无效的循环条件等。
-
数组越界:访问数组时超出了数组的有效范围。
-
语义冲突:代码存在歧义或语义冲突,例如函数返回类型与函数定义不一致、重载函数无法区分等。
-
缺少库文件或链接错误:在链接阶段找不到需要的库文件或链接时出现错误。
-
操作符错误:使用了错误的操作符或操作符的操作数类型不匹配。
编译型错误需要在编译前进行修复,通常会在编译器输出错误信息,指示出错的代码行数和具体错误信息,以帮助开发人员进行修复。
1.2链接型错误
编程链接型错误是指在将多个源文件链接成可执行文件时出现的错误。链接器负责将不同源文件中的代码和数据合并在一起,并解决函数和变量的引用关系。
看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不存在或者拼写错误。
如下图所示:

以下是一些常见的链接型错误:
-
未定义的符号:代码中引用了其他源文件中定义的函数或变量,但链接器找不到其定义。
-
多重定义:多个源文件中定义了同名的函数或变量,链接器无法决定使用哪一个定义。
-
符号重定位错误:链接器无法正确将不同源文件中的代码和数据关联起来。
-
重复符号:同一个源文件中定义了多次同名的函数或变量。
-
引用符号解析错误:链接器无法正确解析函数或变量的引用关系。
-
缺少库文件:链接器无法找到需要的库文件或库文件不完整。
-
内存溢出:链接后的可执行文件大小超过了系统可用的内存空间。
-
地址冲突:多个源文件中定义了具有相同地址的变量。
1.3运行时错误
编程运行时错误是指在程序执行过程中出现的错误,也称为异常。这些错误会导致程序的意外行为或崩溃。
借助调试,逐步定位问题,最难搞。
如下图所示:

这里我们使用函数递归来遍历二叉树时,将递归结束条件屏蔽后,就会出现栈溢出导致程序运行错误
以下是一些常见的运行时错误:
-
空指针异常:当程序试图访问一个空指针时引发的错误。
-
数组越界异常:当程序试图访问数组中超出有效索引范围的元素时引发的错误。
-
除以零异常:当程序试图执行除以零的操作时引发的错误。
-
类型转换异常:当程序试图将一个不兼容的数据类型转换为另一种类型时引发的错误。
-
文件操作异常:当程序试图打开、读取或写入文件时发生了错误。
-
内存分配异常:当程序试图分配或释放内存时出现错误。
-
栈溢出:当程序递归调用层级过深或使用过多局部变量时导致程序栈溢出。
-
死锁:在多线程编程中,当两个或多个线程相互等待对方释放锁导致程序无法继续执行时发生的错误。
-
无限循环:当程序进入一个无法退出的循环时导致程序永远执行下去。
-
逻辑错误:程序逻辑的错误,导致程序得到错误的结果。
运行时错误通常会导致程序崩溃或产生不可预测的结果。为了解决运行时错误,可以使用调试工具来跟踪错误发生的位置,并检查代码逻辑以发现错误。此外,异常处理机制可以用于捕获和处理运行时错误,使程序在出现错误时能够进行适当的处理,避免程序崩溃。
2.调试
2.1什么是调试
- 调试(Debugging / Debug),又称除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。
- 调试的基本步骤
✨发现程序错误的存在
✨以隔离、消除等方式对错误进行定位
✨确定错误产生的原因
✨提出纠正错误的解决办法
✨对程序错误予以改正,重新测试
2.2Debug和Release的介绍
Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。
我们写代码通常使用debug版本:

Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
3.Windows环境调试介绍
首先在环境中选择 debug 选项,才能使代码正常调试。
如下图所示:

3.1使用快捷键

最常使用的几个快捷键:
- F5
启动调试,经常用来直接跳到下一个断点处。 - F9
创建断点和取消断点
断点的重要作用,可以在程序的任意位置设置断点。
这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去。
例如,当我们发现使用二叉树前序遍历时程序会异常,经过思考我们发现可能是前序遍历函数出现的问题,就可以在使用前序遍历函数的那一行按下F9创建断点,然后按下F5启动调试,程序直接跳到前序遍历函数这里:

使用F5开始调试:

- F10
逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。 - F11
逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最长用的)。

开始调试后,进入前序遍历函数内部,进行逐语句调试
-
CTRL + F5
开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用。 -
停止调试就可以点击如下图所示的红色图标

- 想知道更多快捷键?点我
3.2调试的时候可以查看的程序信息
3.2.1查看临时变量的值
在调试开始之后,用于观察变量的值。
步骤如下图所示:

使用断点,开始调试到断点位置后,就可以使用F11逐语句调试,然后就可以利用监视查看当前临时变量的值了,如下图所示:

这里我们发现数组还没有初始化,这是因为第79行还没有执行,当我们按下F11进行下一句的时候,数组就会初始化完毕了:

3.2.2查看内存信息
在调试开始之后,用于观察内存信息。
步骤如下图所示:

使用断点,开始调试到断点位置后,就可以使用F11逐语句调试,然后就可以利用内存观察内存信息了,如下图所示:

如果想显示的更清楚一些,可以将显示的列改成4列,让它一行显示4个字节:


对于我们想查看的内存信息,可以在上方地址栏输入我们已知的地址进行查看:

我们知道数组名就是数组首元素地址,所以我们在地址栏直接输入数组名,回车即可:

这样我们就可以看到每个地址对应的值了,注意这里是十六进制显示
3.2.3查看调用堆栈
通过调用堆栈,可以清晰的反应函数的调用关系以及当前调用所处的位置
步骤如下图所示:

结果如下:

3.2.4查看汇编信息
可以切换到汇编代码,查看反汇编可以帮助我们更好地理解程序的执行过程和内部运行机制
步骤如下图所示:

还有一种比较直接的方法:
当调试开始后,鼠标单击右键,选择转到反汇编

结果如下:

3.2.5查看寄存器信息
可以查看当前运行环境的寄存器的使用信息。在调试过程中,查看寄存器信息可以帮助我们了解程序运行的状态和指令的执行过程。
步骤如下图所示:

结果如下:

4.多多动手,尝试调试
一定要熟练掌握调试技巧。
初学者可能80%的时间在写代码,20%的时间在调试。但是一个程序员可能20%的时间在写程序,但是80%的时间在调试。
多多使用快捷键,提升效率
✨实例
求 1!+2!+3! …+ n! ;不考虑溢出。
//sum = 1! + 2! + 3! +...
int main()
{int i = 0;int sum = 0;//保存最终结果int n = 0;int ret = 1;//保存n的阶乘scanf("%d", &n);for(i=1; i<=n; i++){int j = 0;for(j=1; j<=i; j++){ret *= j;}sum += ret;}printf("%d\n", sum);return 0;
}
这时候我们如果3,期待输出9,但实际输出的是15。
如下图所示:

我们发现结果与我们预期实现的结果不一样,这表明我们的代码可能有点问题,如果直接观察或读代码无法找出错误原因,我们就可以通过调试来寻找错因:
- 首先我们知道整个实现逻辑的重点在for循环那里,错误很可能在那里出现,所以我们就在for循环那里按F9打下断点

- 然后F5开始调试

- 在控制台输入3后,使用F11逐行调试,并搭配监视窗口观察变量值

- 发现问题

我们发现当循环到
i = 3时,在计算3!时ret应该等于3*2 = 6,而这里ret = 12,再仔细观察发现:
当开始计算3!时,ret是从2开始乘积的,所以造成了3!=12,故每次计算完阶乘我们都应该将ret置为1
- 正确代码

5.结语
在写代码时,我们不可避免会出现一些错误,以下是一些提高代码正确率的小tips:
- 使用assert
- 尽量使用const
- 养成良好的编码风格
- 添加必要的注释
- 避免编码的陷阱
以上就是今天所有的内容啦~ 大家要注意多多练习,完结撒花~ 🥳🎉🎉
相关文章:
掌握高效实用的VS调试技巧
🔥 个人主页:大耳朵土土垚 1.编程常见的错误 1.1编译型错误 编程编译型错误是指在编译代码时发现的错误。编译器在编译过程中会检查代码是否符合语法规范和语义要求,如果发现错误会产生编译错误。 直接看错误提示信息(双击&#…...
实验2 字符及字符串输入输出与分支程序设计实验
字符及字符串输入输出 从键盘输入两个一位十进制数,计算这两个数之和,并将结果在屏幕上显示出来。 分支程序设计 从键盘输入一字符,判断该字符是小写字母、大写字母、数字或者其他字符。若输入为小写字母,显示“You Input a Lo…...
docker容器间网络仿真工具-pumba
docker-tc&pumba docker-tc:docker-tc项目仓库 pumba:pumba项目仓库 这两个项目理论上都可以实现对容器间的网络环境进行各种模拟干预,包括延迟,丢包,带宽限制等。 但是我在实际使用时,发现docker-tc这个工具在进行网络进行模…...
A36 STM32_HAL库函数 之PCD通用驱动 -- B -- 所有函数的介绍及使用
A36 STM32_HAL库函数 之PCD通用驱动 -- B -- 所有函数的介绍及使用 1 该驱动函数预览1.11 HAL_PCD_SOFCallback1.12 HAL_PCD_ResetCallback1.13 HAL_PCD_SuspendCallback1.14 HAL_PCD_ResumeCallback1.15 HAL_PCD_ISOOUTIncompleteCallback1.16 HAL_PCD_ISOINIncompleteCallbac…...
vue2 + element三级菜单实现模板
需求: 需要一个含有三级菜单的结构模板,用于业务快速开发。 解决: sidebar.vue <template><el-menu :default-active"defaultActive" class"el-menu-vertical-demo" active-text-color"#ffd04b"&…...
vue H5页面video 视频流自动播放, 解决ios不能自动播放问题
视频组件 <videostyle"width: 100%; height: 100%;object-fit: fill"class"player"refplayer_big_boxcontrolspreloadautoplay //自动播放muted //是否静音playsinline"true"x5-playsinline""webkit-playsinline"tru…...
自闭症儿童:探索症状背后的多彩内心世界
在星启帆自闭症康复中心,我们每天与一群独特而珍贵的孩子相遇——他们,是自闭症谱系障碍的患儿。自闭症,这一复杂的神经发育障碍,以其多样化的症状表现,为每个孩子的生活轨迹绘上了不同的色彩。 自闭症孩子的症状各异…...
在Centos7上安装PostgreSQL16的详细步骤
文章目录 环境一、准备二、postgresql下载方法一:wget下载方法二:下载压缩包解压 三、创建用户组、用户四、创建数据主目录五、配置环境变量六、initdb初使化数据库七、配置服务八、设置开机自启动九、设置防火墙十、启动数据库服务 环境 CPU: 4 核心或以…...
MySQL 图形化界面
填完信息之后,圆圈处可以验证是否可以连接数据库 展示所有数据库(因为有的可能连上,却没有数据库显示)...
【人工智能】GPT-5的即将到来:从高中生进化到,,,博士生?
GPT-5的即将到来:从高中生进化到,博士生? 随着近月GPT-4o的出世,OpenAI也在进行一系列的采访和介绍接下来的展望和目标。 在6月22日的采访中,美国达特茅斯工程学院公布了OpenAI首席技术官米拉穆拉蒂的访谈内容。穆拉蒂确认&#…...
【收录率高丨投稿范围广 | 往届均已EI检索】第四届光学与通信技术国际学术会议(ICOCT 2024,8月9-11)
欢迎参加第四届光学与通信技术国际学术会议(ICOCT 2024),该会议将于2024年8月9-11日在南京举办。自2021年首次会议以来,ICOCT已经发展成为光学和通信领域较有影响力的国际会议之一,聚焦最前沿的技术进展与未来发展趋势…...
小阿轩yx-LVS负载均衡群集
小阿轩yx-LVS负载均衡群集 构建群集服务器—通过整合多台服务器使用 LVS 达到服务器的高可用和负载均衡并以同一个 IP 地址对外提供相同的服务 LVS 群集应用基础 群集称呼来自英文单词“Cluster”在服务器领域则表示大量服务器的集合体,区分单个服务器 Cluster …...
CPP知识点记录总结
1、类的const成员函数 const成员函数的const 实际修饰的是该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。 class A {void fun() const {// 常成员函数,在函数名后用const修饰} } 一文带你入门C类和对象【十万字详解&#…...
Spring源码(一) 如何阅读 Spring 源码
学习 Spring 的源码,也可以通过 SpringBoot 搭环境。 不管是什么源码,最好写个 demo,跑起来,然后从常用的类和方法入手,跟踪调试。 配置对象 新建一个 SpringBoot 的项目, 详情见: https://b…...
【代码随想录训练营】【Day 63】【单调栈-2】| Leetcode 42, 84
【代码随想录训练营】【Day 63】【单调栈-2】| Leetcode 42, 84 需强化知识点 单调栈强化 题目 42. 接雨水 注意 python 数组反序用法 result [::-1] class Solution:def trap(self, height: List[int]) -> int:# n len(height)# leftMax, rightMax [0] * n, [0] * …...
CTF常用sql注入(一)联合注入和宽字节
0x01 前言 给自己总结一下sql注入的常用姿势吧,记录一下学习 0x02 联合 联合注入的关键词是union SQL的union联合注入原理是联合两个表进行注入攻击,使用union select关键词来进行联合查询。 那么为什么我们在题目中一般是只写一个呢 因为 $sql &quo…...
薄冰英语语法学习--冠词1
冠词有2个,the 和 a /an the 叫定冠词 常用形容一类事务、特指(加强)、放在转有名词前面。 就这3个 定冠词 1. 定冠词特指某个(某些)人或某个(某些)事物 Many people came here to visit the old cast…...
基于Java中的SSM框架实现野生动物公益保护系统项目【项目源码+论文说明】计算机毕业设计
基于Java中的SSM框架实现野生动物公益保护系统演示 摘要 本系统按照网站系统设计的基本流程,遵循系统开发生命周期法和结构化方法,基于Java语言设计并实现了野生动物公益保护系统。该系统基于浏览器/服务器模式,采用JSP技术,后台…...
c->c++(二):class
本文主要探讨C类的相关知识。 构造和析构函数 构造函数(可多个):对象产生时调用初始化class属性、分配class内部需要的动态内存 析构函数(一个):对对象消亡时调用回收分配动态内存 C提供默认构造和析构,…...
11 UDP的可靠传输协议QUIC
1.如何做到可靠性传输 2.UDP与TCP,我们如何选择 3.UDP如何可靠,KCP协议在哪些方面有优势 4.KCP协议精讲(重点讲解 5.OUIC时代是否已经到来 UDP如何做到可靠传输 ACK机制重传机制 重传策略序号机制(后发的包可能先到) 3 2 1-> 2 3 1重排机制 2 3 1-> 3 2 1窗口机制 流…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型
在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重,适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解,并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...

