一.Debug和Release
1.1Dbug通常称为调试版本,它包含调试信息,并且不作任何优化,便于调试程序;
这样编译产生的是debug版本的可执行程序,其中包含调试信息,是可以直接调试的。
1.2Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便于用户很好地使用.当程序员写完代码,测试再对程序进行测试,直到程序的质量符合交付给用户使用的标准,这个时候就会设置为release,编译产生的就是release版本的可执行程序,这个版本是用户使用的,无需包含调试信息等。
1.3两者区别
Debug
Release
其代码执行时编译结果只是字母上的不同其余变化不大,但在文件中应用程序所占的空间大小截然不同,Debug的大小>Release的大小。
二.VS调试快捷键
2.1环境准备
将VS设置为Debug,如图:
2.2调试快捷键
调试最常用的几个快捷键:
F9:创建断点和取消断点。
其中的红点为断点(如下图所示)
断点的作用是可以在程序的任意位置设置断点,打上断点就可以使得程序执行到想要的位置暂定执行,接下来我们就可以使用F10,F11这些快捷键,观察代码的执行细节。
补:当想直接监视i为8的数时用断点的设置
按F9设置断点,鼠标右键打开断点设置输入参数(如下图)
再进行调试则直接会跳转到第八次(如下图)
条件断点:满足这个条件,才能触发断点
F5:启动调试,经常用来直接跳到下一个断点处,一般是和F9配合使用。(F9告诉断点在哪里,F5调试时直接从那里开始)
F10:逐过程,通常用来处理一个过程,一个过程可以是一次函数的调用,或是一条语句。
F11:逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部。在函数调用的地方,想进入函数观察细节,必须使用F11,如果使用F10,直接完成函数调用。
CTRL+F5:开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用。
三.监视和内存观察
调试相当于动作分解一步步来,让我们观察清楚
eg:(先F10调试,再在调试选项内选择窗口)
调试窗口如下图所示
3.1监视
开始调试后,在菜单栏中【调试】 ->【窗口】->【监视】,打开任意一个监视窗口,输入想要观察的对象就行。
打开监视窗口:
在监视窗口中观察:
3.2内存
与监视同理流程【调试】 ->【窗口】->【内存】
内存所展示的内容为
从左往右依次为,内存地址,内存中的数据4进制显示(初始为16进制,途中也可调为4进制),内存中的数据解析只能观察文本信息。
补充:数据在内存中存储的都是二进制的数据。
四.调试举例1
阶乘计算:3!
初次计算结果为:
调试检查错误:
得出结果为在n=3,i=3时出现问题
原因:ret被重复定义
纠正:
五.调试举例2
在VS2022,X86,Debug 的环境下,编译器不做任何优化的话,以下代码执行的结果为什么?
#include<stdio.h>
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;
}
结果:死循环打印hehe
分析:
其中数组只能存在10个元素,但循环次数却达到了13次(包含等于12)且在监视中可以观察到从一开始,arr[10], arr[11], arr[12]中存在随机数
当i的值为0时arr[12]的值也为0,由此可推断i和arr[12]可能会存在某种关系
再次验证地址:
如图所示:两者所用的为同一个地址。由此开始循环。
局部变量,存储到栈区。i和arr不是连续的。
5.1栈区内存的使用习惯时从高地址向低地址使用的,所以变量i的地址是比较大的。arr数组的地址整体是小于i的地址。
【数组在内存中是连续存放的,随着下标的增长,地址是由低到高变化的】
5.2数组在内存中的存放是:随着下标的增长,地址是由低到高变化的。
六,编程常见错误归类
6.1编译型错误
常为语法错误
eg:
6.2链接型错误
主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是因为
(1)标识符名不存在
(2)拼写错误
(3)头文件没包含
(4)引用的库不存在
6.3运行时错误
用调试来解决此问题。