目录
1.前言介绍
1.介绍有关于vs的调试之前,先了解一下,我们为什么要调试?
2.而Bug的最开始的意思是指“虫子”,那么谁创造的这一个全新的意思呢?
2.常见错误归类
3.调试
1.什么是调试?
2.vs里的debug和release模式
1.Debug
2.Release
那么当release版本的进行了调试,结果会是什么结果呢?
3.调试的快捷键
4.监视和内存观察
1.监视
2.内存
简单补充其他调试窗口(仅供了解):
5.数组调试案例
总结
1.介绍有关于vs的调试之前,先了解一下,我们为什么要调试?
——>有Bug 这个单词现在是指在电脑系统中或者程序中,隐藏着的一些未被发现的缺陷问题,简称程序漏洞
2.而Bug的最开始的意思是指“虫子”,那么谁创造的这一个全新的意思呢?
“Bug”的创始人格蕾丝·赫柏(Grace Murray Hopper),是一位为美国海军工作的电脑专家,也是最早将人类语言融入到电脑程序的人之一。而代表电脑程序出错的“bug” 这名字,正是由赫柏所取的。1947年9月9日,赫柏对Harvard Mark II设置好17000个继电器进行编程后,技术人员正在进行整机运行时,它突然停止了工作。于是他们爬上去找原因,发现这台巨大的计算机内部一组继电器的触点之间有一只飞蛾,这显然是由于飞蛾受光和热的吸引,飞到了触点上,然后被高电压击死。所以在报告中,赫柏用胶条贴上飞蛾,并把“bug”来表示“一个在电脑程序里的错误”,因此“Bug”这个说法一直沿用到今天。
代码中的错误比较杂,有时候代码运行不成功但是又看着没什么问题,这里把常见的错误分一下类
1.链接错误→编译无法发现这个错误,唯有生成才能发现看错误提示信息,主要在代码中找到错误信息的标识符,而错误原因往往有:
标识符名不存在、拼写错误、头文件未包含、引用的库未存在。
2.编译错误→一般都是语法错误,一般会有具体错误的语法提示例如:当test()没写;号时,他会出现这个画面。|语法错误一般比较容易发现,随着对语言的掌握越来越熟练,这个错误会出现的越来越少。
3.运行错误→一切正常,结果错误其他都是正常的,各种原因导致的,需要调试去找到问题所在,隐藏比较深
补:当然还有其他的错误类型比如逻辑错误、系统错误...
调试简单来说就是照着程序一步一步走,看看程序有没有按照预期运行
如果没有按照预期走,那么代码就是有问题的,那就要我们可以从调试中看出问题所在,也就是“bug”所在的地方。
1.Debug
调试版本
调试信息,便于调试程序观察程序运行
编译产生的为debug版本的可执行程序,因此包含调试信息,可以直接调试。
2.Release
发布版本
在这个模式下对代码进行优化,不能一步一步调试,在内存和运行速度上进行了很大程度的改善
它的内存比较小,因为这里面没有用于调试的信息了。
那么当release版本的进行了调试,结果会是什么结果呢?
例如:
#include
int main(){ for(int i=0;i<10;i++){ printf("%d",i); } return 0; } 当尝试一步一步的调试的时候,发现直接一步进行完了,并没有进入for循环,但是结果仍然是正确的,release版本下的调试不是一步一步的去进行,而是直接一步到位进行程序输出结果。
F9:创造断点和取消断点
Ctrl+F9: 停止断点
断点:打上断点就可以使得程序执行到想要的位置暂定执行,接下来就可以一步一步开始观察代码的细节
条件断点:满足这个条件,才触发断点
F5: 启动调试
Ctrl+F5: 开始执行(不=调试)
Shift+F5: 停止调试
Ctrl+Shift+F5: 重启调试
Ctrl+Shift+F9: 删除全部断点
F10:逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句
Ctrl+F10:运行到光标处
F10:逐语句,每一次都执行一条语句,这个快捷键可以使我们的执行进入函数内部,一步一步观察函数内部的运行。
调试中如果想要观察代码执行中,上下代码变量的值,就可以使用监视和内存观察
1.位置:在调试开始后,点开调试
然后在调试中点窗口→监视
下图是监视的样子(i是自己输进去的),可以观察程序中变量的变化
调试→窗口→内存(打开任意一个都可以)
在内存窗口观察数据
打开后是这个样子的
如果想要看变量的地址那么就在内存的地址栏中输入&i或者是数组名即可
例如:
而内存窗口显示也是可以设置的,
这里可以设置显示的列数。
自动窗口:可以显示变量的变化,不用自己输入想看的值,自动显示
局部变量: 有时候和自动窗口显示的是一样,不过只显示局部变量。
反汇编:
寄存器:
#include
int main(){
int i;
int arr[10]={1,1,1,1,1,1,1,1,1,1};
for(i=0;i<13;i++){
arr[i]=0;
printf("%d",arr[i]);
}
return 0;
}
显然代码有错误,数组越界访问了,然而运行结果是无限循环输出0:
咦,不应该是出错吗?为什么会陷入死循环呢?
注:这里是在debug+x86的环境下运行的(使用vs2022版本)
那就来调试看一看到底哪里出错了:
一步一步调试结果每一步发现好像这个arr[12]和i都一样,都随着循环增加
当运行到超出数组范围的时候,发现好像也可以被赋值,而运行完这个for循环之后循环又从新开始了,i又从0开始增加了,我们打开内存发现
i和arr[12]竟然是同一块地址,那么说明当创建这个变量的时候它和i放的地方一样。
那,为什么呢?
这就需要借用其他的知识了,
当我们创建数组时会存放在内存的栈区
而在栈区内一般先使用高地址再使用低地址的空间,所以高地址上先被i占了一个空间,然后数组再按照:随着下标的增长,地址是由高到低变化的规则,所以意味着arr[9]在高地址,和i有一段空间的距离,但是因为在循环的过程中arr[10]、arr[11]、arr[12]被开辟了,而arr[12]显然和i在一个空间了,当循环进行到arr[12]=0时,i也被赋值0了,所以才会接着进行循环,导致循环不结束→死循环
vs的基本的调试功能介绍完毕,当然还有一些本文未介绍到的功能,可以下去自己研究研究,文中介绍到的一些功能还需要下去自己亲自尝试一下(*>◡❛),感谢观看,欢迎点赞收藏૮(˶ᵔ ᵕ ᵔ˶)ა