VS的调试技巧

目录


前言

在VS的学习过程中,会不断的进行程序的调试,去不断的修改、优化程序,那么本篇文章将给你介绍一些关于vs的调试技巧。


提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是bug?

        Bug一词的原意是“昆虫”或“虫子”;而在电脑系统或程序中隐藏着的一些未被发现的缺陷或问题,人们也叫它“bug”。

        Bug”的创始人格蕾丝·赫柏(Grace Murray Hopper),是一位为美国海军工作的电脑专家,也是最早将人类语言融入到电脑程序的人之一。而代表电脑程序出错的“bug” 这名字,正是由赫柏所取的。1947年9月9日,赫柏对Harvard Mark II设置好17000个继电器进行编程后,技术人员正在进行整机运行时,它突然停止了工作。于是他们爬上去找原因,发现这台巨大的计算机内部一组继电器的触点之间有一只飞蛾,这显然是由于飞蛾受光和热的吸引,飞到了触点上,然后被高压电击死。所以在报告中,赫柏用胶条贴上飞蛾,并把“bug”来表示“一个在电脑程序里的错误”,“Bug”这个说法一直沿用到今天。

二、什么是调试(debug)

        在运行程序时出现报错或者结果不符合预期等问题时,那么接下来就该找问题所在,并修复问题,甚至可以进行优化程序的操作。

        而找问题这一步骤的过程就称为调试,英文名debug——destroy bug(摧毁bug,即消灭bug)的意思。

        调试一个程序的前提,是得承认或认为该程序存在问题,然后尽可能的去找出程序中的“虫子”,采用的方法可能是逐条或者逐过程的,亦或屏蔽某段代码、设置断点的方式进行的;然后找出问题所在,分析问题产生的原因,接着修复、完善程序,直到再调试程序正常运行且输出结果符合预期。

1.debug和release

Debug被称为调试版本,它包含调试信息,并且不做任何优化,方便程序员不断的进行调试,修改程序;

release被称为发布版本,它往往是进行了各种优化,使程序在代码大小和运行速度上是最优的,以方便用户使用。当程序员写完代码,不断的测试,直到符合用户和使用标准,注释就可以设置为releasr,编译生成release版本的可执行程序,这个版本是用户使用的,无需包含调试信息等

对比可以看出,同一段代码,编译生成的可执行文件,release版本比debug版本要小很多。

1.1.release可执行程序生成

        在上一篇文章中所写的扫雷(简化版)程序,如果想分享给小伙伴,那么该怎么做?接下来跟我一起来康康。

        第一步:在程序没有bug的情况下,将debug切换为release

        第二步: 重新生成解决方案

        这样就生成了release版本的可执行程序,接着只需要到对应路径寻找.exe文件分享即可。小伙伴只需要打开该程序就能够游玩你的扫雷小游戏。

2.vs调试快捷键

F5 - 启动调试,经常用来直接跳到下一个断点处

        默认情况下,程序不会进入调试模式,代码会瞬间从开头执行到末尾。要想观察程序的内部细节,就得让程序在某个地方停下来,我们可以在这个地方设置断点。
        所谓断点(BreakPoint),可以理解为障碍物,人遇到障碍物不能行走,程序遇到断点就暂停执行。

F9 - 创建断点和取消断点,可以在程序的任意位置设置断点,使得程序在想要的位置随意停止执行

        利用F9设置断点后,鼠标右击断点,选择条件,可以选择合适的x取值,配合F5跳到该x值处,而不用一条语句一条语句的执行。

F10 - 逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句

F11 - 逐语句,就是每次都执行一条语句,可以使执行逻辑进入函数内部

CTRL + F5 - 开始执行不调试

3.监视和内存观察

3.1.监视

        当一段代码没有printf显示输出结果时,如下列代码:

#include<stdio.h>

int main() {
	int arr[10] = { 0 };
	int num = 100;
	char c = 'w';
	int i = 0;
	for (i = 0; i < 10; i++) {
		arr[i] = i;
	}
	return 0;
}

        而你又想观察其中变量的数值,那么这时候可以用到监视窗口,观察变量的数值;但观察的前提条件一定是开始调试后观察。

        未开启调试,监视窗口不显示:

        F10开始调试后,监视窗口选项才出现: 

        而想观察其中变量的数值情况,只需要在监视窗口输入对应的变量名, 逐过程或逐语句执行,观察变量的数值:

3.2.内存

        如果 监视窗口看得不够仔细,也可以采用观察变量在内存中的存储情况,打开内存窗口操作与监视类似:

由于内存是利用观察对象的地址来观察,所以需要获取观察对象 ;如果观察对象是数组,直接输入数组名,如:arr+回车

        若为其他变量,需要加取址符&,如:&num;num被赋值为100,为什么内存中却显示64呢?原来数据在内存在存储的都是二进制的数据,为了方便查看,以16进制的形式显示,100的二进制码为: 0110 0100 变为16进制(2的4次方为16,所以1个16进制数代表4个二进制数) 6(0110 )4(0100)。

         其中:

 4.调试案例

        4.1.求1~n阶乘之和

代码如下:

#include<stdio.h>
int main() {
	int n = 0;
	printf("请输入阶乘数:");
	scanf("%d", &n);
	int ret = 1;   //n阶乘 
	int out = 0;   //阶乘和
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= i; j++) {
			ret *= j;
		}
		out += ret;
	}
	printf("\n%d的阶乘和为%d", n, out);
	return 0;
}

 发现当求1~3!时结果为15,理论上1~3!应该为1!+2!+3!=1+2+6=9

        通过调试发现,在求完1!和2!后,ret的值还在不断的叠加,导致3!=2*2*3=12,最后输出为1+2+12=15 

        只需要对ret在第一次循环时重新赋值即可,但通过上面分析,发现n!=n*(n-1)!,可以较大的减少计算,因此程序可优化为:

#include<stdio.h>
int main() {
	int n = 0;
	printf("请输入阶乘数:");
	scanf("%d", &n);
	int ret = 1;   //n阶乘 
	int out = 0;   //阶乘和
	for (int i = 1; i <= n; i++) {
		ret *= i;
		out += ret;
	}
	printf("\n%d的阶乘和为%d", n, out);
	return 0;
}

4.2.数组赋0,打印hehe

 代码如下:

#include<stdio.h>
int main() {
	int i = 0;
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	for (i = 1; i <= 12; i++) {
		arr[i] = 0;
		printf("hehe\n");
	}
	return 0;
}

        运行发现在不断地打印hehe,光标不断闪烁,说明陷入了死循环:

通过调试发现arr[12]的地址与i的地址是一样的,当给arr[12]赋0的时候同时给i赋0,这样不断地陷入循环。

         利用下图可以理解: 

         tips:当数组进入函数时(不传参情况下),监视无法看到数组全部值时,可以在监视窗口采用,一维数组:arr(数组名),10(数组元素个数);二维数组:arr(数组名),3(数组行数)。

 三.编程的常见错误归类

1.编译型错误

        能够检查语法错误,双击错误时能够出现箭头,大概率定位到错误上下的位置或环境

2.链接型错误

        一般是标识符名不存在或者拼写错误,头文件没包含,引用库不存在等引起的

3.进行时型错误

        运行时错误,变化万千,需要借助调试,逐步定位问题位置,调试解决的是运行时的问题。


总结

        以上就是今天要讲的内容,本文仅仅简单介绍了vs的调试技巧,简单介绍了如何调试以及错误类型。

  • 28
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值