【实用调试技巧】总是找不到Bug?手把手教你在vs2022中调试程序

news/2024/11/25 10:32:59/

🦄个人主页:修修修也

🎏所属专栏:程序调试及报错解决

⚙️操作环境:Visual Studio 2022


目录

什么是Bug?

1947年9月9日:第一个"Bug"被发现

什么是调试?

调试是什么?

调试的基本步骤

Debug和Relese的区别

1.调试的区别

2.文件大小的区别

3.反汇编的区别

4.代码执行结果不同

windows环境下如何进行调试

1.调试环境的准备

2.常用调试快捷键

3.调试时查看程序相关信息

📌查看临时变量的值

🎏查看单一变量

🎏查看数组成员

🎏查看结构体成员

 📌查看内存信息

📌查看调用堆栈

📌查看汇编信息

🎏第一种方式

🎏第二种方式

📌查看寄存器

一些练习的例子

实例一:实现代码:求1!+2!+3!+...n!

 实例二

如何写好易于调试的代码

优秀的代码:

常见的Coding技巧:

需要注意学习的点:

编程常见的错误

📌编译型错误

📌链接型错误

📌运行时错误

结语


什么是Bug?

先来看看百度翻译对Bug的解释:

 而这个让无数程序员感到每天都被噩梦支配的恐惧也有一段有趣的过往:

1947年9月9日:第一个"Bug"被发现

“1947 年 9 月 9 日,我们晚上调试机器的时候,开着的窗户没有纱窗,机器闪烁的亮光几乎吸引来了世界上所有的虫子。果然机器故障了,我们发现了一只被继电器拍死的飞蛾,翅膀大约 4 英寸。”

格蕾丝·霍普(Grace Hopper)用发夹取出飞蛾,把它粘在日志里,并标注:“First actual case of bug being found”(找到了第一个 Bug)。这件计算机史上的奇闻轶事,使“Bug”作为计算机领域的专用词汇,一直沿用至今。

历史上第一个bug图像

什么是调试?

既然有Bug的存在,那么作为程序员肯定要找Bug并且改Bug.

我们把找Bug的过程叫做调试.

我们在写代码的时候一定多思考,不然很容易像这样:

不会调试的程序员排查Bug现状:

 一个高质量的程序员一定要拒绝迷信式改Bug!


调试是什么?

调试(Debugging / Debug):又称除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程.


调试的基本步骤

  • 发现程序错误的存在
  • 以隔离,消除等方式对错误进行定位
  • 确定错误产生的原因
  • 提出纠正错误的解决办法
  • 对程序错误予以改正,重新测试

Debug和Relese的区别

Debug 通常称为调试版本,它包含调试信息,并且不作任何优化便于程序员调试程序


Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的以便用户很好地使用.

1.调试的区别

在Debug环境下,按F10(有fn键的话,需要按住fn+F10),启动调试,就可以使用如下功能了:

而在Release环境下,调试不好用,虽然也可以显示调试界面,但是完成不了像debug环境下的操作。


2.文件大小的区别

Debug环境生成的文件,里面因为包含了调试信息,所以占据的空间较大

Release环境下生成的文件,是提供给用户使用不需要用户调试,所以文件所占空间较小


3.反汇编的区别

Debug:较多

 Release:较少


4.代码执行结果不同

如下代码:

int main()
{int i = 0;int arr[10] = { 0 };for (i = 0; i <= 12; i++){arr[i] = 0;printf("hello\n");}return 0;
}

Debug环境下,结果是死循环:

但在Release环境下却输出了13个"hello":

造成该结果的原因主要是Release环境会优化代码,使程序列在代码大小和运行速度上达到最优,以便用户能够很好地使用它。


windows环境下如何进行调试

1.调试环境的准备

首先我们要在编译器中选择Debug选项,才可以进行正常调试:


2.常用调试快捷键

vs2022中找到调试按钮,鼠标放上去就可以看到可以进行的操作及其快捷键.

常用快捷键有:

F5

启动调试,经常用来直接跳到下一个断点处.


F9

创建断点和取消断点
断点的重要作用,可以在程序的任意位置设置断点。
这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去.


F10

逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。


 

F11

逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最常用的)


 

Ctrl+F5

开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用

想知道更多快捷键?VS中常用的快捷键大全


3.调试时查看程序相关信息

📌查看临时变量的值

🎏查看单一变量

当我们需要观察临时变量的值时,可以先按下F10/F11进入调试,然后在调试中选择:调试-窗口-监视-监视1,就可以打开监视窗口了.

然后在监视窗口输入想观察的变量,敲下回车就可以观察这个变量了.


🎏查看数组成员

当我们需要观察数组中的成员时,可以输入"数组名,大小",然后点击旁边的小三角可以一次性查看全部的数组成员了.


🎏查看结构体成员

当我们需要观察结构体中的成员时,可以输入结构体名,然后点击旁边的小三角可以一次性查看全部的结构体成员了.


 📌查看内存信息

调试开始之后(按下F10/F11)后,用于观察内存信息.

内存窗口如下:

 如果不习惯看16列的数的话,也可以选择将它改为4列:

 

观察内存可以直接输入地址观察,也可以写取地址表达式观察:

这样输入它然后敲回车就可以直接带你找到该变量在内存中的位置:


📌查看调用堆栈

通过调用堆栈,可以清晰的反应函数的调用关系以及当前调用所处的位置.


📌查看汇编信息

在调试开始之后,有两种方式转到汇编.

🎏第一种方式

在空白区右击鼠标,选择"转到反汇编":

然后就可以查看汇编信息了:

🎏第二种方式

在调试开始后,点击"调试-窗口-反汇编"即可查看汇编信息.

效果如下:


📌查看寄存器

进入调试后,点击"调试-窗口-寄存器"即可查看当前运行环境的寄存器的使用信息.


一些练习的例子

师傅领进门,修行靠个人.下面有几个可以调试的例子,大家可以拷贝进自己的编辑器边调试边分析这些代码的问题到底出在哪里.

实例一:实现代码:求1!+2!+3!+...n!

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.

在调试中我希望大家可以搞清楚:为什么会这样?哪一步出了问题?如何解决?


 实例二

#include <stdio.h>
int main()
{int i = 0;int arr[10] = { 0 };for (i = 0; i <= 12; i++){arr[i] = 0;printf("hello\n");}return 0;
}

 这个例子我希望大家可以结合查看内存信息以及查看变量的方法来找出让程序陷入死循环的原因.


如何写好易于调试的代码

优秀的代码:

  1. 代码运行正常
  2. Bug很少
  3. 效率高
  4. 可读性高
  5. 可维护性高
  6. 注释清晰
  7. 文档齐全

常见的Coding技巧:

  1. 使用assert (如果有不太清楚assert函数用法的可以移步这篇博客:不想改bug?程序员必须学会使用的报错函数assert!(断言函数详解))
  2. 尽量使用const
  3. 养成良好的编码风格
  4. 添加必要的注释
  5. 避免编码的陷阱

 多看和学习大佬是如何编写优秀的代码的,如下面是一个模拟实现库函数strcpy的代码:

/***
*char *strcpy(dst, src) - copy one string over another
*
*Purpose:
* Copies the string src into the spot specified by
* dest; assumes enough room.
*
*Entry:
* char * dst - string over which "src" is to be copied
* const char * src - string to be copied over "dst"
*
*Exit:
* The address of "dst"
*
*Exceptions:
*******************************************************************************/
char* strcpy(char* dst, const char* src)
{char* cp = dst;assert(dst && src);while (*cp++ = *src++); /* Copy src over dst */return(dst);
}

需要注意学习的点:

  1. 分析参数的设计(命名,类型),返回值类型的设计
  2. assert的使用.(如果有不太清楚assert函数用法的可以移步这篇博客:不想改bug?程序员必须学会使用的报错函数assert!(断言函数详解))
  3. 野指针,空指针
  4. const的使用
  5. 注释的添加

编程常见的错误

📌编译型错误

直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单。

📌链接型错误

看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。

一般是标识符名不存在或者拼写错误。

📌运行时错误

借助调试,逐步定位问题。


结语

没有什么技能是天生就会的,都是通过后天的不断学习和练习最终掌握的,希望大家可以做一个有心人,积累排错经验。也祝大家"0 Error 0 Warning",Bug全Free!希望这篇博客能对大家有所帮助,一起学习,一起进步!

相关文章推荐

有关“函数用于调用的参数太少”问题解决办法

【C语言】结构体的大小是如何计算的?(结构体对齐)

......




http://www.ppmy.cn/news/1155382.html

相关文章

代码随想录算法训练营第五十三天|309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费

代码随想录算法训练营第五十三天|309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费 309.最佳买卖股票时机含冷冻期714.买卖股票的最佳时机含手续费 309.最佳买卖股票时机含冷冻期 题目链接&#xff1a;309.最佳买卖股票时机含冷冻期 文章链接 状态&#xff1a;有…

ESP8266 Node Mcu开发板连接WIFI并上报数据到MQTT服务器——物联网应用开发

一、前言 本文主要介绍关于ESP8266 Node Mcu开发板如何连接WIFI并将本地采集的数据上传到MQTT服务器中。 大家调试可以使用MQTTBox 二、WIFI连接 首先&#xff0c;导入WIFI连接所需的头文件&#xff0c;引入所需库。 #include <ESP8266WiFi.h> 声明字符串常量&#xff0…

HarmonyOS应用开发者基础认证【满分答案】

HarmonyOS应用开发者基础认证 一、判断题二、单选题三、多选题 一、判断题 在Column和Row容器组件中&#xff0c;justifyContent用于设置子组件在主轴方向上的对齐格式&#xff0c;alignItems用于设置子组件在交叉轴方向上的对齐格式。&#xff08;正确&#xff09; 所有使用C…

ELF和静态链接:为什么程序无法同时在Linux和Windows下运行?

目录 疑问 编译、链接和装载&#xff1a;拆解程序执行 ELF 格式和链接&#xff1a;理解链接过程 小结 疑问 既然我们的程序最终都被变成了一条条机器码去执行&#xff0c;那为什么同一个程序&#xff0c;在同一台计算机上&#xff0c;在 Linux 下可以运行&#xff0c;而在…

pyqt5移动鼠标时显示鼠标坐标

问题&#xff1a; 只有按住鼠标左键或者右键移动的时候才会获取坐标值&#xff0c;即使对QLabel控件使用setMouseTracking(True)也无法解决。 解决方法&#xff1a; 在初始化构造函数中加入 self.setMouseTracking(True) self.centralwidget.setMouseTracking(True) 并且对…

SpringMVC的拦截器(Interceptor)

拦截器简介 SpringMVC的拦截器Interceptor&#xff0c;主要是对Controller资源访问时进行拦截的基本操作的技术&#xff0c;当然拦截后可以进行权限控制&#xff0c;功能增强等都是可以的。拦截器类似于JavaWeb开发中的Filter&#xff0c;他们之间的区别如下图所示 Filter技术…

Ubuntu22安装Docker engine(apt安装方式)

一、准备工作 新创建一个虚拟机。 进入虚拟机&#xff1a; 二、安装docker docker现在对用不同主机提供了不同安装包&#xff1a;docker engine 和 docker desktop。 docker desktop适用于图形化的桌面电脑&#xff0c;docker engine适用于服务器。我们这里当然是安装docker…

模型预测控制(MPC)中考虑约束中的不确定性(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…