在我们编写代码的时候难免会遇到很多问题,我们光靠眼睛是很难看出来哪里出问题了,这时我们往往需要动手一步一步的运行程序找出问题的所在,这个过程就是调试的过程。在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?
现在提起bug,大都想到的是「程序错误、漏洞」,其实bug的原意为「昆虫」
为什么变成这样呢? 因为世界上第一个程序错误就是由一只昆虫所造成的
1947年9月9日,葛丽丝·霍普(Grace Hopper)发现了第一个电脑上的bug。当在Mark II计算机上工作时,整个团队都搞不清楚为什么电脑不能正常运作了。经过大家的深度挖掘,发现原来是一只飞蛾意外飞入了一台电脑内部而引起的故障(如图所示)。这个团队把错误解除了,并在日记本中记录下了这一事件。也因此,人们逐渐开始用“Bug”(原意为“虫子”)来称呼计算机中的隐错。 —— 维基百科
二:什么是调试
所谓调试(Debug),就是让代码一步一步慢慢执行,跟踪程序的运行过程。 比如,可以让程序停在某个地方,查看当前所有变量的值,或者内存中的数据;也可以让程序一次只执行一条或者几条语句,看看程序到底执行了哪些代码。
2.1:调试的基本步骤
- 发现程序错误的存在
- 以隔离、消除等方式对错误进行定位
- 确定错误产生的原因
- 提出纠正错误的解决办法
- 对程序错误予以改正、重新测试
2.2:Debug和release版本的介绍
Debug通常称为调试版本,它包含调试信息,并且不做任何优化,以便于程序员调试。
Release称为发布版本,它往往是进行了各种优化,使得程序在代码的大小和运行速度上都是最优的,以便用户更好的使用。
可以看出在文件大小上有了明显的差异。
下面,我们用一个代码示例来说明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的改变,最终死循环。
注:
i和arr是局部变量
局部变量是放在栈区上的
栈区上内存的使用习惯是:先使用高地址处的空间,再使用低地址处的空间。
数组随着下标的增长,地址是由低到高变化。
三:Windows调试环境介绍
3.1:调试环境的准备
注:Debug可以调试,Release不可以调试。
在环境中选择Debug选项,才可以正常调试。
3.2:快捷键的使用
我们介绍几个最常用的快捷键:
F9:设置断点或取消断点,可以在任意位置设置,这样可以使得程序在想要的位置停下来。
F5:启动调试,往往与F9设置断点配合使用,使开始调试就跳到断点处。
F10:逐过程调试,一个过程可以是一条语句,也可以是一个函数。遇到函数不进入函数内部。
F11:逐语句调试,每次执行一条语句,可以使执行逻辑进入函数内部。shift+F11跳出函数。
CTRL + F5:开始执行不调试。
设置断点+F5 再F10或者F11(进入函数内部) shift+f11 退出函数
3.3:调试查看当前程序信息
3.3.1:查看临时变量的值
在调试开始之后,用于观察各个变量值的变化;
3.3.2:查看内存信息
在调试开始之后,用于观察内存信息;
3.3.3:查看寄存器信息
3.3.3:查看调用堆栈
通过查看调用堆栈,我们可以看出函数的调用关系以及当前调用所处的位置;
四:调试实例
下面我们给出一个简单的调试实例,让大家可以切身体会一下调试的过程,朋友们可以动手试一试。
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!!!观众老爷们,这里只是介绍了简单的调试技巧,如果朋友们觉得有一点点作用的话,希望朋友们能够给予小菜鸟一点支持!后续继续给朋友们带来更好的博文,还希望朋友们能够继续关注,小菜鸟致力于把自己的学习经验与个人理解更多的分享给大家,望大家喜欢与指正。