系列文章目录
文章目录
前言
在代码的编写过程中,调试是一个必不可少的环节,我们在运行代码时都需要进行调试,来检查代码是否能达到自己想要的效果,现在,我就向大家讲述一下如何进行调试。
一、调试
1.定义
调试(英语:Debugging / Debug),又称除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。
调试最基本的原则,代码是否按自己想的运行方式运行。
2.调试的基本步骤
(1)发现程序错误的存在
(2)以隔离、消除等方式对错误进行定位
(3)确定错误产生的原因
(4)提出纠正错误的解决办法
(5)对程序错误予以改正,重新测试
在调试的过程中,我们常用一些快捷键来帮助我们完成调试,具体的快捷键与功能会在下面详细讲解
3.Debug和Release的介绍。
Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。
Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。
我们所说调试都是在Debug版本的环境中,找代码中潜伏的问题的一个过程。
Debug版本是调试版本,编译器编译时会增加一些调试信息,编译器基本不会对其进行优化;一般在开发完成后发布工程前,调试代码都是在Debug模式下进行的
Release版本是不能调试的,一般都是在Debug版本下调试的,Release版本一般编译器会进行大量的优化,删除无用的代码,指令的次序调整等,让其速度更快;Release版本最终是要发送给用户的,发给用户的版本必须要没有问题,测试人员就是最后一个把关的
在Release版本中进行的优化:比如
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = { 0 };
for (i = 0; i <= 12; i++)
{
arr[i] = 0;
printf("hehe\n");
}
return 0;
}
这个代码在Vs 编译器中的Debug模式下编译,会出现死循环,但是,在 release 模式去编译,程序没有死循环。
二、调试使用的快捷键及其功能
注意:在调试之前要确保处于Debug模式
1.CTRL + F5
开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用
如果代码没有错误, CTRL + F5后我们会得到自己想要的结果;有问题的话会执行错误或者显示的结果不是自己所预期的,这时候,我们就需要用到以下快捷键的来进行调试了。
例1
int main()
{
char a[] = "张三";
printf("%s",a);
return 0;
}
此处代码无错误,CTRL + F5后得到结果
例2:
2.F5
启动调试,经常用来直接跳到下一个断点处。
F5一般会与F9配合使用,用于快速的跳转到有问题的地方,加快调试效率;如果没有设置断点,那么F5的执行结果会与CTRL + F5的结果一样,直接显示出外面语句执行的结果。
3.F9
创建断点和取消断点
断点的重要作用,可以在程序的任意位置设置断点。
这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去。
F5一般会与F9配合使用,用于快速的跳转到右问题的地方,加快调试效率;
4.F10
逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。
这个是按照主函数中的语句执行,按一次执行一个过程,如果其中你调用了函数,会直接显示出函数执行的结果,而不是进入这个函数的语句中
比如:
void test1()
{
}
void test2()
{
}
int main()
{
int a = 0;
int b = a + 1;
int c = b + 2;
test1();
test2();
return 0;
}
在这个函数中,它不会进入test1与test2中,只会得到执行的结果。
5.F11
逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最常用的)。
每按一下,执行一条语句,如果调用了函数,那么他会进入这个函数中,接着继续一条一条语句的执行下去。
例如:
int main()
{
int a = 0;
test1();
return 0;
}
这里就进入了test1函数中。
三、调试时查看程序当前信息(常用)
注意:以下功能在调试开始后,才能使用
1. 查看临时变量的值
例如:
int main()
{
int a = 0;
int b = a + 1;
int c = b + 2;
return 0;
}
2.查看内存信息
例如:
int main()
{
int a = 0;
int b = a + 1;
int c = b + 2;
return 0;
}
如观察的列数太多了,可对其进行调整
3.查看调用堆栈
通过调用堆栈,可以清晰的反应函数的调用关系以及当前调用所处的位置。
例如:
void test1()
{
}
void test2()
{
}
int main()
{
int a = 0;
int b = a + 1;
int c = b + 2;
test1();
test2();
return 0;
}
四、常见的错误
1.编译型错误
直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单。
例1:
int main()
{
int a = ;
return 0;
}
改正:
int main()
{
int a = 0;
return 0;
}
例2:
int main()
{
char a = "张三";
printf("%s",a);
return 0;
}
改正后:
int main()
{
char a[20] = "张三";
printf("%s",a);
return 0;
}
2.链接型错误
看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不存在或者拼写错误。
例1:
#define _CRT_SECURE_NO_WARNINGS
int main()
{
int a = 0;
printf("%d",a);
return 0;
}
改正:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>//添加了头文件的引用
int main()
{
int a = 0;
printf("%d",a);
return 0;
}
3.运行时错误
不能通过错误列表或者观察发现错误,借助调试,逐步定位问题,最难搞。
例1:(需要在VS编译器中运行)
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = {0};
for(i=0; i<=12; i++)
{
arr[i] = 0;
printf("hehe\n");
}
return 0;
}
错误列表:
结果:死循环的打印hehe
这个时候就需要自己调试找出错误的原因。