Debug:调试版本,没有优化,便于调试。(文件大小较大)
Release:发布版本,进行优化。(文件大小较小)
我们先引出一段代码
int main()
{
int i = 0;
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (i = 0; i <= 12; i++)
{
printf("hehe\n");
arr[i] = 0;
}
return 0;
}
这个代码在Debug版本情况下是无限循环打印hehe,为什么是这样呢?在for循环中明明已经越界访问了,为什么不报错?接下来我们在release版本下进行打印
hehe hehe hehe hehe hehe hehe hehe hehe hehe hehe hehe hehe hehe 请按任意键继续. . .
在release版本下打印的结果为13个hehe,13个hehe表示for循环执行13次的结果,并且没有报错,为什么相同的代码在不同的版本下打印的结果不同呢?
接下来,我们使用调试技巧来进行检验:首先我们来进行学习调试快捷键
F5启动调试——最好和F9配合使用 F9设置断点(切换断点) F10逐过程 F11逐语句(能够进入函数内部) shift+F11跳出函数内部 shift+F9快速监视 shift+F5停止调试 自动窗口:在程序执行的过程中,自动把程序执行到光标上下位置的某些变量放在监视窗口中去去(提取出来) 局部变量:监视光标附近的局部变量;
我们先来调试一段代码
int main()
{
int i = 0;
for (i = 0; i < 100; i++)
{
printf("%d", i);
}
for (i = 0; i < 100; i++)
{
printf("%d", 10 - i);
}
return 0;
}
我们可以发现,代码主要问题在第二个for循环,我们可以通过把鼠标移到第二个for循环的位置。按F9设置断点,按F5配合断点,这时候,我们会发现代码直接启动调试并且直接进行到我们设置的断点
如图所示,我们执行了断点之前的全部代码。断点的意义:代码执行在断点处,并且停下来。接下来,我们按F5,进入到调试界面
我们可以发现i的值变成了1
再按一次,结果变成了2.由此可见,F5实际的意思是跳到代码执行逻辑的下一个断点处,因为这里的是for循环,所以i值增加
接下来,解释F10的作用,F10是逐过程,我们写一个简单的求和代码
多次按 F10进行逐过程调试
重点是314 到315,我们在逐过程分析中,直接跳过了Add(a,b)函数,没有访问函数的内部。这里的逐过程是把函数的一次调用当成了一个过程,所以没有访问函数内部 如何解释局部变量窗口:我们设置这样一个代码进行解释
我们在mian函数中额外创建了一个局部变量,可以发现,这个局部变量窗口收录了tmp,但随着我们按F10进行逐过程,如图所示
窗口中的tmp不见了,因为光标的位置移动了,局部变量的意思是收录光标附近即所以语句内的局部变量
调用堆栈:我们先构建函数
void test2()
{
printf("hehe\n");
}
void test1()
{
test2();
}
void test()
{
test1();
}
int main()
{
test();
return 0;
}
可以发现,这个代码写的是main函数调用test函数,test函数调用test1函数,test1函数调用test2函数,接下来我们进行调用堆栈
在main函数内部,可以看到只有一个exemain
当我们用逐语句使光标移动到test函数内部时,看到有两个,并且表示test函数的还在上面
当我们用逐语句使光标移动到test1函数内部时,看到有三个,并且test2在最上面
同理,我们可以发现调用堆栈的调试和栈类似,栈的特点:先进先入,后进先出,接下来我们看它是否满足后进先出
可以发现,最后进入堆栈的test2最先退出
接下来,test1退出。由此可见,调用堆栈和栈的特点类似,使用这种调试能够检验函数彼此之间的调用关系。