调试技巧——C语言

156 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天 @TOC


一、BUG是什么?

简单地说,BUG就是你程序中的问题,因为有这个bug的存在导致你的程序无法达到你预期的效果 在这里插入图片描述

这是计算机史上第一次正视程序的问题,当时是因为一个 ==小虫子(bug)== 导致的问题,所以就出现了我们后来的bug

二、什么是调试?

1.调试

调试是我们程序员自己去发现寻找程序问题的过程。:warning::warning::warning:

2.调试的过程

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

3.Debug和Release

在这里插入图片描述

我们打开vs可以看到程序分为:==debug==和==release==版本,那他两到底有什么区别尼???:snowflake::snowflake::snowflake:

在这里插入图片描述

==Debug 通常称为调试版本==,它包含调试信息,并且不作任何优化,便于程序员调试程序。 ==Release 称为发布版本==,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优 的,以便用户很好地使用。

在这里插入图片描述 在这里插入图片描述

我们顺着文件目录可以找到这段程序,大家可以分别保存下==debug==和==release==版本,分别看看有什么区别。 :snowflake: :snowflake: :snowflake:release为发布版本,当你保存后不能进行直接的修改。

三、如何调试?

1.环境准备

在这里插入图片描述 上一章节讲到,我们要想进行调试,必须选择debug版本。

2.VS相关快捷键

在这里插入图片描述

==F5==开始调试,经常用来直接跳到下一个断点处。 ==Ctrl+F5==开始执行(不调试) ==F9==创建断点和取消断点 断点的重要作用,可以在程序的任意位置设置断点。 这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去。 ==F10==逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。 ==F11==逐语句,通常是用来进入函数进行调试。

3.常查看相关信息

在这里插入图片描述

:triangular_flag_on_post::triangular_flag_on_post::triangular_flag_on_post:==查看临时变量的值==

在这里插入图片描述

:triangular_flag_on_post::triangular_flag_on_post::triangular_flag_on_post:==查看内存信息==

在这里插入图片描述

:triangular_flag_on_post::triangular_flag_on_post::triangular_flag_on_post:==查看堆栈信息==

在这里插入图片描述

:triangular_flag_on_post::triangular_flag_on_post::triangular_flag_on_post:==查看汇编信息==

在这里插入图片描述

:triangular_flag_on_post::triangular_flag_on_post::triangular_flag_on_post:==查看寄存器信息==

在这里插入图片描述

四、常见编程的错误?

1.编译型错误

:rose::rose::rose:通常都是一些语法错误,凭借经验就可以解决。

在这里插入图片描述 在这里插入图片描述 我们可以根据提示,很容易就修改成功了,这里是在定义数组时未加分号,我们添加上即可。

2.链接型错误

:rose::rose::rose:看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不存在或者拼写错误

在这里插入图片描述 在这里插入图片描述 我们可以根据下面的提示发现,我们未定义add函数直接使用导致程序的错误。

3.运行时错误

:rose::rose::rose:这种问题一般是程序无报错,可以正常运行但达不到预期效果,这是大家就可以借助刚刚所讲到的调试技巧进行逐步调试去发现问题的所在,并纠正。

五、调试案例分析

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;
}

:pencil2::pencil2::pencil2:大家思考下这段程序如果输入3的话,会输出多少尼?

在这里插入图片描述 进行运行之后发现,结果并不是9,而是15,为什么尼?那我们进行一步一步调试去发现问题所在。 在这里插入图片描述 当我们就进行第一轮循环时,阶乘ret为1,sum为1. 在这里插入图片描述 当进行第二轮循环,ret为2,sum为3也没有问题。 在这里插入图片描述 当进行第三轮循环时,阶乘为12,sum为15时,我们可以发现第三轮循环时ret为12,不是6,可以发现问题在这。 在这里插入图片描述

:pencil2::pencil2::pencil2:我们可以发现,每轮进行阶乘计算时,为进行初始化,而是沿用上一轮计算的结果,导致结果出现了问题。

在这里插入图片描述

当我们调试之后,很容易就发现了问题的所在,并进行了纠正,==这就是调试的重要性==。