当前位置:   article > 正文

做程序员的核心的核心------调试技巧-----超详细讲解_程序员的调试指南

程序员的调试指南

上课!

行则将至,道阻且长

在这里插入图片描述

1.什么是bug?

2.调试是什么?有多重要?
调试的基本步骤:
Debug和Release的介绍

3.windouws环境调试介绍
调试环境的准备
调试快捷键的使用介绍
调试的时候查看程序当前信息

4.一些调试的实例

文末:实践是检验真理的唯一标准!

1.什么是bug? 下面来讲一个历史小故事

Bug其实原意是臭虫或者虫子的意思。
这名字,是由于早期一台巨大的电脑,历史上的第一台计算机是一台非常非常大的电脑,跟一间房子一样大。人们要进到房子里面检查计算机是否工作。

有一天一位计算机科学家去值班的时候,发现计算机不工作了,于是就进到房间里面检查,发现二极管上有一只臭虫死在那里了,换掉二极管后计算机就能正常工作。当天晚上该科学家把臭虫的照片贴在了日志上。如下图:
在这里插入图片描述

所以在报告中,科学家用胶条贴上飞蛾,并把“bug”来表示“一个在电脑程序里的错误”,“Bug”这个说法一直沿用到今天。

这就是bug的由来,总的来说,bug就是计算机不按正常要求运作了。

2.调试是什么?

下面我们看一段话:

  • 所有发生的事情都一定有迹可循,如果问心无愧,就不需要掩盖也就没有迹象,如果问心有愧,就必然需要掩盖,那就一定会有迹象,迹象越多就越容易顺藤而上,这就是推理的途径。

一名优秀的程序员是一名出色的侦探。

每一次调试都是尝试破案的过程。

这是我这个初学者的日常,不知道有没有引起你的共鸣… ╮( ̄▽  ̄)╭

在这里插入图片描述

所以我们要:拒绝迷信式调试!

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

2.1调试的基本步骤:

  • 发现程序错误的存在

发现程序错误的人大部分是程序员自己。 一个产品是什么样子的,按什么按钮产生什么样的界面,都是由产品经理设计的:

产品经理按照市场需求设计产品: 由程序员按照产品的样子去上开发产品,就是敲代码
然后由测试人员照着产品的功能进行测试,就是对程序员开发好的产品进行测试,发现bug就是报给程序员,程序员对bug再进行修改。
到这里,可以发现,程序员和测试人员像是一对
“天敌”,一个要少写bug,一个要多测出bug
考核就是考察测试人员测出多少bug,考察程序员写出多少bug

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

2.2Debug和Release

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

  • 在这里插入图片描述

  • 当我们进行调试时,选择Debug

  • 这里以vs2019(所包含的编辑器+编译器+调试器为IDE)为例
    请看下面的代码,当我们进行调试时(F10),第一次循环结束后,

  • 可以观察到 i 和 sum 的值的变化。

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

以上面的演示为例
在这里插入图片描述

  • 可以看到,i 和sum 甚至 a 的值都未被定义
  • 可以得出–Release是无法进行调试的
  • –Release是发布版本, 是通过调试之后,没有发现问题,再发布出去,所以在Release环境下发布是没有调试信息的。

我们来验证一下:

在这里插入图片描述
在这两个文件下,打开Debug文件夹:
在这里插入图片描述
打开Release文件:
在这里插入图片描述
可以发现,这两个exe文件的大小是不同的,差别比较大,所以Release文件是没有调试信息的。

3.windows环境调试介绍

3.1调试环境的准备:

在这里插入图片描述

  • 更改成该环境下就可以了

3.2调试中的快捷键的使用介绍

  • 注意:一定要按下F10开始调试时,才能看到各种调试的快捷键‘
  • 未开始调试时,是这个样子的在这里插入图片描述
  • 按下F10开始调试之后,可以看到各种各样的功能,下面来介绍核心部分

在这里插入图片描述

F5

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

F9

  • 创建断点和取消断点 断电的重要作用,
  • 可以在程序的任意位置设置断点
  • 这样就可以是的程序在想要的位置随意停止执行
  • 继而一步步执行下去
  • 这两个快捷键经常是配合使用的

下面来操作一下
在这里插入图片描述

  • 然后按下F5,这里没有直接跳到断点处的原因是要输入a和n的值

在这里插入图片描述

  • 可以看到,当输入完成时,直接就跳到了断点处

在这里插入图片描述

  • 问你:当设置这两个断点时,再次按下F5,会不会从第一个断点跳到第二个断点呢?

在这里插入图片描述

  • 答案是不会。因为按下第二次断点时,程序的调试步骤是这样的:

在这里插入图片描述

  • 由于循环条件满足,会再次循环,再次遇到第一个断点,可以通过k的值和sum的值还要i的值来证明,又循环了一次。所以当循环不满足时,按下F5,才会直接来到第二个断点处。
  • 如果想按下F5跳到最后一个断点呢?
  • 直接把第一个断点取消掉
  • 在这里插入图片描述
  • 此时再次按下F5,就会直接到最后的断点

总结:按下F5直接跳到断点处的前提是中间没有阻碍(即没有限制条件,如:要输入值,循环之间没有断点等等)。

  • 当学到后面,写到上千行代码的时候,进行调试的时候设置断点就很有必要了,(要相信自己能写到一千行代码)

  • -再补充一点,可以再红色框框处的灰色地带点击鼠标,也可以设置断点
    在这里插入图片描述

  • F10

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

  • (我的理解是:F10会把任何东西当成一行东西来看待,不管那一行是否调用函数,就算这一行是调用函数,也不会进入函数内部)

  • 在这里插入图片描述

  • F11

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

  • (按F10的理解,F11就会认认真真执行每一行,也会进入函数内部)

  • 在这里插入图片描述

  • ctrl+F5

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

3.3 调试的时候查看程序当前信息

3.3.1查看临时变量的值

1.监视窗口(监视窗口是用的非常非常非常频繁的)
按如下图所示,在调试起来后,一步一步操作,四个监视可以任选一个,然后在监视名称下面输入临时变量的值,这里以a和b为例
在这里插入图片描述

输入a和b的值,就能够在监视窗口见到
在这里插入图片描述

甚至可以在监视里面计算:
在这里插入图片描述
监视还可以查看数组的内容:
在这里插入图片描述

2.自动窗口
按如下图所示操作,可以找到自动窗口
在这里插入图片描述

可以看到,自动窗口是非常智能的,能够准确给出代码中的变量和其他值
在这里插入图片描述

  • 但是!正因为它太智能,带来弊端,进入函数内部之后,发现a和b的值在自动窗口中就看不到了,假如本来我们就算想看a和b的值,它会擅作主张地删掉增加修改一些东西,反而达不到目的。这就是自动窗口的弊端。

在这里插入图片描述
3.局部变量
会加载一些在上下文中产生出来的局部变量,只展示局部变量

可以看到,类似于自动窗口,局部变量也会擅自修改局部变量,反而达不到想要观察某个局部变量的目的。

  • 在这里插入图片描述
    综上,最最最好用的就是监视了,它用得非常非常普遍的。

4.内存
按F10开始调试后,就能找到内存,如图:
在这里插入图片描述
输入arr后,可以看到其内存中存储了十个数,从右到左读取,是由于 “小端” 的原因,具体会另外一篇文章进行讲解
在这里插入图片描述

  • 一个整型占4个字节,所以每行都存储数组中的各个元素。

5.查看调用堆栈
在这里插入图片描述
所谓的堆栈:可以理解成一个谷仓:如下图

在这里插入图片描述

  • 看懂上面的图,就能够理解下面的堆栈了:

在这里插入图片描述

  • 我们在打开堆栈时,显示的页面可能是大部分空白,这时候右击鼠标,点击显示外部代码即可查看
    可以看出,真的就像一个谷仓,函数调用时放进内存里,当不再使用时,就拿出去。这个过程的专有名词叫 “压栈”。
    在这里插入图片描述

4.调试的一些实例

求阶乘为例:

(故意写错代码,为了演示调试的强大)
int main()
{
	int i = 0;
	int ret = 0;
	int n = 0;
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
	{
		ret *= i;
	}
	printf("%d", ret);

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 当想要求5的阶乘是,5!=120才对,然而输出结果是0,假如自己找了很久觉得自己的代码没有什么错误,但输出结果就是错的,这就需要调试。

在这里插入图片描述

  • 具体的调试方法上面已经介绍的非常详细啦,万事需要动手,才能get到要点,看完别忘了亲自动手实践喔!

  • 再给一个实例:

(实例2:下面代码也有错误,请改正一下)
//求1!+2!+3!+...+m!
int main()
{
	int i = 0;
	int ret = 1;
	int n = 0;
	int sum = 0;
	int m = 0;
	scanf("%d", &m);
	for (n = 1; n <= m; n++)
	{
		for (i = 1; i <= n; i++)
		{
			ret *= i;
		}
		//求n的阶乘
		sum += ret;//每次求完就加起来
	}
	printf("%d", sum);

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 输入3时,求应该是3!+2!+1!=9,然而事与愿违

在这里插入图片描述

看到这里,你已经足够强大了,剩下得就是亲自动手实践!

**实践是检验真理的唯一标准!!**

休息片刻,你可以深入了解调试(2)

下课!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/888914
推荐阅读
相关标签
  

闽ICP备14008679号