【C语言基础】实用调试技巧

在我们编写代码的时候难免会遇到很多问题,我们光靠眼睛是很难看出来哪里出问题了,这时我们往往需要动手一步一步的运行程序找出问题的所在,这个过程就是调试的过程。在IT界流传着这么一句话“一名优秀的程序员也是一名优秀的侦探”所以当我们遇到问题时,还是要多动手,尝试调试,才能有进步。希望大家多多给予支持,赠人玫瑰,手有余香!

文章目录

  • 一:什么是Bug?
  • 二:什么是调试
    • 2.1:调试的基本步骤
    • 2.2:Debug和release版本的介绍
  • 三:Windows调试环境介绍
    • 3.1:调试环境的准备
    • 3.2:快捷键的使用
    • 3.3:调试查看当前程序信息
      • 3.3.1:查看临时变量的值
      • 3.3.2:查看内存信息
      • 3.3.3:查看寄存器信息
      • 3.3.3:查看调用堆栈
  • 四:调试实例
  • 五:如何写出好的代码
    • 5.1:什么是优秀的代码
    • 5.2:常用的Coding技巧

一:什么是Bug?

【C语言基础】实用调试技巧_第1张图片

现在提起bug,大都想到的是「程序错误、漏洞」,其实bug的原意为「昆虫」
为什么变成这样呢? 因为世界上第一个程序错误就是由一只昆虫所造成的
【C语言基础】实用调试技巧_第2张图片

1947年9月9日,葛丽丝·霍普(Grace Hopper)发现了第一个电脑上的bug。当在Mark II计算机上工作时,整个团队都搞不清楚为什么电脑不能正常运作了。经过大家的深度挖掘,发现原来是一只飞蛾意外飞入了一台电脑内部而引起的故障(如图所示)。这个团队把错误解除了,并在日记本中记录下了这一事件。也因此,人们逐渐开始用“Bug”(原意为“虫子”)来称呼计算机中的隐错。 —— 维基百科

二:什么是调试

所谓调试(Debug),就是让代码一步一步慢慢执行,跟踪程序的运行过程。 比如,可以让程序停在某个地方,查看当前所有变量的值,或者内存中的数据;也可以让程序一次只执行一条或者几条语句,看看程序到底执行了哪些代码。

2.1:调试的基本步骤

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

2.2:Debug和release版本的介绍

Debug通常称为调试版本,它包含调试信息,并且不做任何优化,以便于程序员调试。
【C语言基础】实用调试技巧_第3张图片
【C语言基础】实用调试技巧_第4张图片

Release称为发布版本,它往往是进行了各种优化,使得程序在代码的大小和运行速度上都是最优的,以便用户更好的使用。
【C语言基础】实用调试技巧_第5张图片
在这里插入图片描述
可以看出在文件大小上有了明显的差异。

下面,我们用一个代码示例来说明Release相对于Debug版本发生了优化。
代码示例:

int main()
{
	int i = 0;
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	for (i = 0; i <= 12; i++)
	{
		arr[i] = 0;
		printf("hehe\n");
	}
	return 0;
}

上述代码在Debug版本中运行时导致了死循环,而在Release版本编译时,程序没有死循环。这之中的区别就是因为优化问题而出现的。
这是因为在一些编译器中,在栈中储存如果i和arr之间的空间适合的话,就有可能使用的arr数组向后越界就访问到了i,造成循环变量i的改变,最终死循环。
【C语言基础】实用调试技巧_第6张图片

注:
i和arr是局部变量
局部变量是放在栈区上的
栈区上内存的使用习惯是:先使用高地址处的空间,再使用低地址处的空间。
数组随着下标的增长,地址是由低到高变化。

三:Windows调试环境介绍

3.1:调试环境的准备

注:Debug可以调试,Release不可以调试。
【C语言基础】实用调试技巧_第7张图片
在环境中选择Debug选项,才可以正常调试

3.2:快捷键的使用

我们介绍几个最常用的快捷键:
F9:设置断点或取消断点,可以在任意位置设置,这样可以使得程序在想要的位置停下来。
F5:启动调试,使开始调试就跳到断点处,向后跳到写一个逻辑上的断点,不要直接点F5(直接结束了),往往与F9设置断点配合使用。
F10:逐过程调试,一个过程可以是一条语句,也可以是一个函数。遇到函数不进入函数内部。
F11:逐语句调试,每次执行一条语句,可以使执行逻辑进入函数内部。shift+F11跳出函数。
CTRL + F5:开始执行不调试。
【C语言基础】实用调试技巧_第8张图片
设置断点+F5 再F10或者F11(进入函数内部) shift+f11 退出函数

3.3:调试查看当前程序信息

3.3.1:查看临时变量的值

在调试开始之后,用于观察各个变量值的变化;
【C语言基础】实用调试技巧_第9张图片

3.3.2:查看内存信息

在调试开始之后,用于观察内存信息;
【C语言基础】实用调试技巧_第10张图片

3.3.3:查看寄存器信息

【C语言基础】实用调试技巧_第11张图片

3.3.3:查看调用堆栈

通过查看调用堆栈,我们可以看出函数的调用关系以及当前调用所处的位置;
【C语言基础】实用调试技巧_第12张图片

四:调试实例

下面我们给出一个简单的调试实例,让大家可以切身体会一下调试的过程,朋友们可以动手试一试。

int main()
{
	int n = 0, sum = 0;
	int ret = 1;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= i; j++)
		{
			ret *= j;
		}
		sum += ret;
	}
	printf("%d\n", sum);
	return 0;
}

如果我们输入3,正确答案应该是9,而程序运行相互来确实15,这时我们可以通过调试找出问题的所在。

五:如何写出好的代码

5.1:什么是优秀的代码

  • 代码运行正常;
  • Bug很少;
  • 效率高;
  • 可读性高
  • 可维护性高;
  • 注释清晰;
  • 文档齐全;

5.2:常用的Coding技巧

  • 使用assert();
  • 合理使用const;
  • 养成良好的编码习惯;
  • 添加必要的注释;

OK!!!观众老爷们,这里只是介绍了简单的调试技巧,如果朋友们觉得有一点点作用的话,希望朋友们能够给予小菜鸟一点支持!后续继续给朋友们带来更好的博文,还希望朋友们能够继续关注,小菜鸟致力于把自己的学习经验与个人理解更多的分享给大家,望大家喜欢与指正。

你可能感兴趣的:(学习分享,笔记,IT,c语言,开发语言,后端)