0
点赞
收藏
分享

微信扫一扫

实用调试技巧【想笑着写代码吗/程序员内功修炼】

代码敲到深夜 2022-03-11 阅读 31

目录

前言

1. bug是什么?

2. 调试是什么?有多重要?

 我们是如何写代码的?

又是如何排查出现的问题的呢?​

2.1 调试是什么?

2.2 调试的基本步骤

2.3 Debug和Release的介绍

​ 3. Windows环境调试介绍

3.1 调试环境的准备

3.2 快捷键

3.3 调试的时候查看程序当前信息

3.3.1 查看临时变量的值/内存信息

 3.3.2 查看调用堆栈

3.3.3 查看汇编信息

3.3.5 查看寄存器信息

 4. 调试的实例

4.1 实例1

4.2 实例2

5. 常见错误

5.1 编译型错误

5.2 链接型错误

 5.3 运行时错误

6. 优秀的代码


前言

        调试即排错,对程序调试,是每一位程序员的必备技能。但大神们总是能在短短几分钟内找到我们要找很久的bug。调试需要积累经验,不像语法规定那样,bug不是千篇一律,它随时有可能出现在任何地方。

        但并不是没有规律可循,我们可以通过定位,缩小范围来找到问题,下面就让我们开始内功修炼之路吧!

        以下皆以VS2019为例。

1. bug是什么?

        

这是计算机史上发现的第一个bug,它的原意为臭虫。现在是计算机程序漏洞的别称。

2. 调试是什么?有多重要?

 我们是如何写代码的?

又是如何排查出现的问题的呢?

 如果csdn有弹幕功能的话,大概我的屏幕会被"真实"塞满。

我们在开始找错时,总是会不知道问题在哪,一段时间后,修修改改后好像知道问题在哪一部分,但难以再细致地找错。这就是我们掌握的调试技巧不够,经验不足造成的。

2.1 调试是什么?

发现和减少错误不等于消除错误,程序是人写的,难免会有bug。

2.2 调试的基本步骤

一般调试流程如下,下面会有详细的介绍

2.3 Debug和Release的介绍

     下面时同一段代码被编译生产的.exe文件的大小

▶️Debug

▶️Release

 3. Windows环境调试介绍

(linux开发环境调试工具是gdb,后期会介绍。)

3.1 调试环境的准备

3.2 快捷键

经常使用的快捷键

▶️假设按下了F11,调试----窗口里面有不少非常重要的功能,它能让我们看到程序在内存中的执行情况。 

▶️ 假设我要看a的值是怎么变化的以及a的地址,打开监视和内存窗口:

 内存窗口中要输入&a,回车后,才能找到a的地址

▶️在各自的窗口中右击鼠标的菜单中也有选项:

 ▶️按下按钮也可停止调试,窗口都会被关闭:

3.3 调试的时候查看程序当前信息

3.3.1 查看临时变量的值/内存信息

▶️在监视/内存窗口添加好变量后,继续按F11/F10让语句按顺序执行;或者用鼠标按在指定行前的绿色箭头,执行到某一行,注意观察临时变量的值/内存信息是否符合预设。

 3.3.2 查看调用堆栈

通过调用堆栈,可以清晰的反应函数的调用关系以及当前调用函数所处的位置。

查看/梳理:代码/模块的调用逻辑。

3.3.3 查看汇编信息

有两种方式

▶️右击鼠标

▶️调试---窗口

 反汇编/调用堆栈以后会详细介绍,通过汇编语言,我们可以更深入地了解语句在内存中的执行方式、顺序。

3.3.5 查看寄存器信息

▶️窗口---寄存器

 寄存器和汇编语言有十分紧密的关系,它也是计算机非常重要的部件,以后会详细讲解。

 4. 调试的实例

4.1 实例1

#include<stdio.h>
int main()
{
	int n = 0;
	//scanf("%d", &n);
	//求n的阶乘
	//1~n的数字
	int i = 0;
	int ret = 1;
	int sum = 0;

	for (n = 1; n <= 3; n++) 
	{
		for (i = 1; i <= n; i++)
		{
			ret *= i;
		}
		sum += ret;
	}
	
	printf("%d\n", sum);

	return 0;
}

ps:这是一个非常简单的例子,所以假装我们不知道错误

▶️运行

结果本应该是9,为什么是15呢?

▶️开始调试---监视 

通过监视sum和ret的值,我们发现,当进行到第三次时,本该是6的ret变成了12,这时便将问题定位到ret ,通过对代码的分析,不难发现其实这是ret未初始化造成的问题。

4.2 实例2

#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;
}

阅读一遍代码,不难发现循环中数组越界了,那么它的结果如何呢?打印12次hehe?

必备知识

▶️看看监视窗口

 

这里的i和arr[12]居然是同一块空间 

▶️上面说到,栈区内存是先使用高地址的空间的,图来

 

 

5. 常见错误

5.1 编译型错误

一般是语法错误,通过查看错误信息或根据经验可较快解决。

双击错误信息,编译器会在代码行中提示 

5.2 链接型错误

看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不
存在或者拼写错误。

 5.3 运行时错误

前两种错误运行不起来,运行时的错误需要调试,就像求阶乘累加一样的操作。它是最磨人,也是让人提升能力最大的。

6. 优秀的代码

等我下一篇文章!!

结语

这里只是介绍了调试需要的工具和使用方法,实际上,相比于写代码,我们可能会花更多时间在调试程序上。这是一个优秀的coder必不可少的素质,错误千变万化,我们要不断积累经验,总结,兵来将挡,水来土掩。

举报

相关推荐

0 条评论