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