当前位置:   article > 正文

C语言IDE:VisualStudio实用调试技巧_vs studio c语言调试技巧

vs studio c语言调试技巧

引子: 什么是bug

BUG的英文释义是“虫子”,现在人们通常会将计算机上发生的一些问题,比如系统缺陷、程序漏洞、轻微毛病、问题、故障等统称为bug(漏洞),人类历史上第一个程序BUG就是与虫子有关。
1937年,有一天,计数人员在对一台计算机调试程序时出现故障,经过一阵子周折,发现有只飞蛾被烤糊在两个继电器触点的中间导致短路。于是把程序故障统称为“臭虫BUG”。

1. 调试及其重要性

所有的发生的事情都一定有迹可循,对于电脑程序来说也是如此,当问题出现时就一定有导致其发生的成因,迹象,迹象越多就越容易顺藤摸瓜,发现问题所在,着就是推理的途径,也是调试程序的方式。
在我们编写程序时,随着代码体量增大,功能的增多,就不免会出现各种各样的问题,如何发现解决这些问题,让程序正常运行。我们就需要依靠调试这一手段,接下来我们就来进行相关学习。

1.1 什么调试

调试(英语:Debugging / Debug),又称除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。

1.2 调试的基本过程

  1. 发现程序中错误的存在
  2. 以隔离,消除等方式对错误进行定位
  3. 确定错误产生的原因
  4. 提出纠正错误的解决方式
  5. 对程序出现的错误进行改正,重新测试。

注解步骤2:
隔离,消除的思想:从程序主干开始,一步一步将各个功能区释放,直至出现所发现的错误。或是分步将程序的功能区一次注释隔离,当程序不再报错时,当前备注的功能区即为错误所在。

1.3 Debug与Release

在这里插入图片描述

Debug通常被称为调试版本,它包含调试信息,并对程序不做任何优化,便于程序员调试程序。
Release称为发布版本,此版本的程序进行了各种优化,电脑在编译时不会为程序包含调试信息,使得程序在代码大小与运行速度上都是最优的,便于用户更好地使用。

当分别以不同模式编译程序时,会生成不同地目标文件。
在这里插入图片描述

2. windows调试环境调试介绍

2.1 调试环境地准备

环境选项中应选择debug选项,在此环境下代码才能正常调试。
在这里插入图片描述

2.2 调试中的快捷键

方式1:想要开始调试,可在菜单栏选中(调试 -> 开始调试)选项进行调试。

在这里插入图片描述

也可以通过快捷键进行调试,调试中最常用到的几个快捷键,如下:

F5

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

F9

创建断点与取消断点
断点:可以在程序任意位置设置断点,使得程序可以在想要停止执行的地方停止,然后再进行一步步调试

F10

逐过程地调试,一个过程可以是指一次函数地调用,或是一条语句。

F11

逐语句,即为每次执行一条语句,同时使用这个快捷键可以使得我们进入函数内部。

CRTL + F5

开始执行程序不调试。

2.3 调试时程序中相关信息地查看

2.3.1 查看临时变量的值

在调试开始后,观察各变量值得变化
在这里插入图片描述
Fn:辅助功能键

2.3.2 查看内存信息(快捷键:Alt + 6)

开始调试后,观察各个内存空间中内容得变化。
在这里插入图片描述

2.3.3 查看调用堆栈

函数调用堆栈:以栈的数据结构显示函数之间的调用关系

void test4()
{
	printf("hello world\n");
}

void test3()
{
	test4();
}

void test2()
{
	test3();
}

void test1()
{
	test2();
}

//示例,显示函数之间的调用关系
int main()
{
	test1();

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

在这里插入图片描述

2.3.4 查看汇编信息(Alt + 8)

查看代码的汇编形式

方式1:右击鼠标,选择(转到反汇编)

在这里插入图片描述

方式2:

在这里插入图片描述

2.3.5 查看寄存器信息(Alt + 5)

程序执行过程中,各个寄存器的变化。

在这里插入图片描述

3. 调试实例

3.1 实例1:

实现:计算1! + 2! + 3! + …+ n!的值

int main()
{
	int i = 0;
	int sum = 0;//保存最终结果
	int n = 0;
	int ret = 1;//保存n的阶乘
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
	{
		int j = 0;
		for (j = 1; j <= i; j++)
		{
			ret *= j;
		}
		sum += ret;
	}
	printf("%d\n", sum);

	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在这里插入图片描述

当我们运行上述代码时,当输入为3时,结果应为1!+ 2!+ 3!= 1 + 1 × 2 + 3 × 2 × 1 = 1 + 2 + 6 = 9,可是我们却得到是15,调试确定问题原因。

ret 变量的值留有上一次计算的值,未清零。

3.2 实例2:

调试找出程序死循环的原因

int main()
{
	int i = 0;
	int arr[10] = {0};
	for (i = 0; i < 12; i++)
	{
		arr[i] = 0;
		printf("hello world\n");
	}

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

一次中方式定义数组与变量,在VS2019环境下,它们的内存空间位置如图,当数组越界访问arr[12]时,会更改掉 i 的值,使得变量永远无法增加至12。

补充:Release版本相较于Debug版本优化的验证
在上述的实例2中,在Debug版本下,此段程序会进行死循环并报错,但当我们以Release环境运行时,代码就会正常运行,当我们再通过内存观察时,数组 arr 的内存位置出现在了变量 i 之前。

在这里插入图片描述
在这里插入图片描述

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号