1.什么是bug?
bug本意是“昆虫”,现在⼀般是指在电脑系统或程序中,隐藏着的⼀些未被发现的缺陷或问题,简称程序漏洞。
“Bug”的创始⼈格蕾丝·赫柏(Grace Murray Hopper),她是一位为美国海军工作的电脑专家。
1947年9⽉9⽇,格蕾丝·赫柏对设置好17000个继电器进行编程后,技术人员正在进⾏整机运时,它突然停止了工作。于是他们爬上去找原因,发现这台巨大的计算机内部⼀组继电器的触点之间 有⼀只⻜蛾,这显然是由于⻜蛾受光和热的吸引,飞到了触点上,然后被高电压击死。所以在报中,赫柏用胶条贴上⻜蛾,并把“bug”来表示“一个在电脑程序里的错误”,“Bug”这个说法⼀直沿用到今天。
赫柏发现第一个“bug”后的手稿
2.什么是调试?
这一称呼后来演变成表达缺陷漏洞的计算机专业术语,人们习惯地把排除程序故障叫做“debug”(除虫)。
调试⼀个程序,⾸先是承认出现了问题,然后通过各种⼿段去定位问题的位置,可能是逐过程的调
试,也可能是隔离和屏蔽代码的⽅式,找到问题所的位置,然后确定错误产⽣的原因,再修复代码,重新测试。
3.Debug和Release
在VS编译器中有着这Debug和Release两个选项,他们分别是调试版本与发布版本。
Debug | 该版本的可执行程序,其中包含调试信息,是可以直接调试的,不做任何优化 |
Release | 它往往是进⾏了各种优化,使得程序在代码大小和运行速度上都是最优的, 用户使⽤的标准 |
4.VS调试快捷键
要在debug的环境下准备开始
常用的代码调试快捷键:
F5 | 启动调试 |
Ctrl+F5 | 开始执行(不调试) |
shift+F5 | 停止调试 |
F9 | 启用/关闭断点 |
Ctrl+F9 | 停止断点 |
F10 | 逐过程 |
F11 | 逐语句 |
Ctrl+E,D(ctrl+k,d) | 格式化全部代码 ;让代码瞬间整洁起来 |
Ctrl+K,C | 注释选定内容 |
Ctrl+K,U | 取消选定注释内容 |
5.监视和内存观察*
在调试的过程中我们,如果要观察代码执⾏过程中,上下⽂环境中的变量的值,有哪些⽅法呢?
这些观察的前提条件⼀定是开始调试后观察。
5.1监视
比如我们要监视下面的代码:
#include<stdio.h>
void test()
{
printf("+++\n");
}
int main()
{
int i = 0;
test();
for (i = 0; i < 10; i++)
{
printf("csdn\n");
}
for (i = 0; i < 10; i++)
{
printf("dream\n");
}
return 0;
}
监视流程:
开始调试后(提前按F11开始),在菜单栏中【调试】->【窗⼝】->【监视】,打开任意⼀个监视窗⼝,输⼊想要观察的对象就⾏
监视变量:通过监视变量的变化,能够更好的发现错误信息
5.2内存
6.调试举例
6.1监视代码
在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("csdn\n");
}
return 0;
}
输出结果:打印死循环“csdn”
为什么会出现死循环,下面我们用监视查找原因:
当i在0-12变化中,可以通过监视器看到arr[i]依次变为0:
接下来,当arr[12]从12变成0时,i也从12变成0:
故i变成0,重新进入for循环.......最后结果出现死循环打印.....
6.2内存布局
上⾯程序的内存布局如图:
1. 栈区内存的使⽤习惯是从⾼地址向低地址使⽤的,所以变量i的地址是较⼤的。
arr数组的地址整体是⼩于i的地址。
2. 数组在内存中的存放是:随着下标的增⻓,地址是由低到⾼变化的。
那随着数组下标的增⻓,往后越界就有可能覆盖到i,这样就可能造成死循环的
(在不同的编译器下可能中间的空出的空间⼤⼩是不⼀样的)
7.小结
注意:栈区的默认的使⽤习惯是先使⽤⾼地址,再使⽤低地址的空间,但是这个具体还是要编译器的实现,⽐如:
在VS上切换到X64,这个使⽤的顺序就是相反的,在Release版本的程序中,这个使⽤的顺序也是相反的。
从这个理解我们能够体会到调试的重要性,只有调试才能观察到程序内部执行的细节。
“ 此时情绪此时天,无事小神仙”