如何让bug远离你?

想让bug远离你,当然是靠佛祖保佑~

cpp 复制代码
/*
 * **************************************************************************
 * ********************                                  ********************
 * ********************      COPYRIGHT INFORMATION       ********************
 * ********************                                  ********************
 * **************************************************************************
 *                                                                          *
 *                                   _oo8oo_                                *
 *                                  o8888888o                               *
 *                                  88" . "88                               *
 *                                  (| -_- |)                               *
 *                                  0\  =  /0                               *
 *                                ___/'==='\___                             *
 *                              .' \\|     |// '.                           *
 *                             / \\|||  :  |||// \                          *
 *                            / _||||| -:- |||||_ \                         *
 *                           |   | \\\  -  /// |   |                        *
 *                           | \_|  ''\---/''  |_/ |                        *
 *                           \  .-\__  '-'  __/-.  /                        *
 *                         ___'. .'  /--.--\  '. .'___                      *
 *                      ."" '<  '.___\_<|>_/___.'  >' "".                   *
 *                     | | :  `- \`.:`\ _ /`:.`/ -`  : | |                  *
 *                     \  \ `-.   \_ __\ /__ _/   .-` /  /                  *
 *                 =====`-.____`.___ \_____/ ___.`____.-`=====              *
 *                                   `=---=`                                *
 * **************************************************************************
 * ********************                                  ********************
 * ********************      				             ********************
 * ********************         佛祖保佑 永远无BUG        ********************
 * ********************                                  ********************
 * **************************************************************************
 */

本文完~


咳咳,直接开始开始正文~


本文的结构:

O,前言

一,什么是bug

二,什么是Debug

三,通用编译器的Debug

(1)打印输出

(2)单步调试

(3)设置断点

(4)监视与内存观察

(5)设置断言

四,编译习惯很重要

(0)从内存的视角写代码

(1)函数的高内聚低耦合

(2)要写注释

(3)适当留白

五,想要告诉你

O,前言

1.本文衔接栏目错误经验分享专栏的内容**(开篇文章附在文末)**

2.我们知道,编码时常见的错误有编译型错误,链接型错误,运行时错误等。本文的重点是运行时错误------具体说------你写出的代码并不能达到你想要的效果,但是你也不知道错在哪里。

3.Debug是我们知道有错误之后采取的行动,为了使程序达到预测的运行目标,我们不得不寻找自己写出的bug,但是这通常会花费很长的时间。如果我们可以在从源头上减少bug的产生,少写一些bug,或者不要为自己将来Debug设置那么多的障碍,那么这在无形之中节约了我们的时间,提高了效率。

一,什么是bug?

bug本意是"昆虫"或"虫子",现在---般是指在电脑系统或程序中,隐藏着的一些未被发现的

缺陷或问题,简称程序漏洞。

"Bug"的创始人格蕾丝·赫柏(Grace Murray Hopper),1947年9月9日,格蕾丝·赫柏对Harvard Mark II设置好17000个继电器进行编程后,技术人员正在进行整机运行时,电脑突然停止了工作。于是他们爬上去找原因,发现这台巨大的计算机内部一组继电器的触点之间有只飞蛾,这显然是由干飞峨受光和热的吸引,飞到了触点上,然后被高电压击死了。

所以在报告中,赫柏用胶条贴上飞蛾,并把"bug"来表示"一个在电脑程序里的错误"。 于是,"Bug'这个说法一直沿用到今天。

二,什么是Debug

De- 是减少,消灭;调试的过程被称为Debug(消灭bug)。

可以通过隔离和屏蔽代码来大体定位问题,确定错误的原因,再修复代码,重新测试。

Debug也是一个版本,与它相对的是Release版本,两个版本各有不同的区别:

区别:

Debug内存占用较大,包含调试信息,相对于Release版本不做优化;

Release版本不含调试信息,由于做了相关优化,内存占用较小;

三,通用编译器的Debug

1.打印输出

使用printf函数跟随程序时时输出变量的值

e.g.1

编写一个程序,使其能根据输入得到符合要求的输出内容。

程序须包含一个函数,该函数能求出一个字符串中最长的单词并输出。

输入

一行可以包含 英文大、小写字母、空格 的字符串。

输出

通过调用函数,输出此字符串中最长的单词。

样例

|-------------------------------------------------------------------------------------------------|
| 标准输入 |
| Einstein had been a famous physicist after then but he still wore the same old overcoat |
| 标准输出 |
| physicist |

理解一下题,我们直接看代码:

cpp 复制代码
#include<stdio.h>
int main()
{
	char arr[50][50] = { 0 };
	int brr[50] = { 0 };
	int j = 0, p;
	char ch;
	
	for (;;)
	{
		p = 0;
		for (; (ch = getchar()) != '\n';)
		{
			
			if (ch != ' ')//如果不是' '则继续读取
			{
				arr[j][p] = ch;
				p++;
			}
			if ((ch) == ' ')//如果是' '则换到j的下一行
			{
				arr[j][p] = 0;
				brr[j] = p;//(计数)
				j++;
				p = 0;
			}
		}
		if ((ch) == '\n')
		{ 
			brr[j] = p;
			break; 
		}
	}
	int tem = 0, k = 0;
	for (; k < 50; k++)//找到最长字符串的长度
	{
		if (tem < brr[k])
		{
			tem = brr[k];
		}
	}
	
	int m = 0;
	for (; m < 50; m++)
	{
		printf("%d\n",m);//时时输出m,查看第几个字符串是最长字符串
		if (brr[m] == tem)
		{
			break;
		}
	}//找到最长字符串对应的行数j
	
	
	printf("%s\n", arr[m]);
	
	return 0;
}

在最后一个for循环中,m用来记录是第几个字符串,用printf持续输出m,当m为5时,m == tem 即前面找到的最长字符串的行数。

于是,这段代码是题目的一种解法。

2.单步调试

在一些程序运行时,我们会看到报错信息,但是我们并不知道具体哪里出了错,这时候,我们能通过单步调试来定位出错的位置

比如这些代码,当我们运行这段代码后,发现程序挂了,但是不知道具体哪一行出现了问题

e.g.2------当我们运行时,发现程序死循环了,但是由于在实际情况中,代码项目往往很复杂,我们一般无法直接目测处错误之处。

cpp 复制代码
#include<stdio.h>
int main()
{
	printf("haha\n");
	main();
	
	return 0;
}

e.g.3------当程序运行时,我们得知程序发生了数组越界,但是我们并不知道具体是哪一行代码导致发生了数组越界(因为我们必须找到代码,才能修改,改进代码)

cpp 复制代码
int main()
{

	char arr[10];
	scanf("%s", arr);
	return 0;
}

这时候是时候让单步调试出场解决问题了:

e.g.2解

当程序运行到main()时,再次按f10

程序就崩溃了

------得出结论:在第6行出现了问题

e.g.3解

当程序运行到scanf()后,再次按f10,程序报错

------得出结论:scanf()函数读入数据过多导致数组越界了

3.设置断点

在VS2019,我们用鼠标单击左侧的代码行的标号,就会出现一个红色的原点,这就是断点

设置断点:

鼠标单击代码行左侧的竖行,会出现断点;(再次单击取消断点)

将输入标稳定在要打断点的行,按f9,也会出现断点。(再次按f9取消设置)

使用断点:

断点与f5配合使用,每按一次f5程序会跳到逻辑上的下一个断点。

4.监视与内存观察

当我们调试的时候,我们想更直观的观察变量的值的变化过程,这时候我们可以打开监视

在按f10进入调试状态,注意是在调试状态下,我们在如图所示的窗口中,找到监视窗口:

(四个监视窗口都是可以使用的,第一次使用的话,可以随便选一个)

在监视窗口中,我们可以随时监视变量的变化过程:

内存窗口:

按图寻找,即可找到内存窗口

通过内存窗口,我们可以看到函数内变量在内存中的创建与销毁**(附在文末)**

因为之前分享过,在这里不再详细展开。

5.设置断言

assert()函数,用于在调试过程中捕捉程序错误

e.g.4------模拟实现strcpy()函数

我们不希望传入的p1,p2是空指针,对空指针解引用是很危险的!所以我们在此处使用断言assert,两个指针不是空指针

cpp 复制代码
#include<stdio.h>
#include<assert.h>
void my_strcpy(char* p1,const char* p2)
{
	assert(p1 != NULL);
	assert(p2 != NULL);
	while(*p1++ = *p2++)
	{
		;
	}
}
int main()
{
	char str1[20] = "xxxxxxxxxxxxxx";
	char str2[] = "hello";

	my_strcpy(str1,str2);

	printf("%s\n", str1);
	printf("%s\n", str2);
	return 0;
}

(这段代码是非常巧妙的,它生动体现了C语言的紧凑性。)

如果是,那么程序会报出精确的错误信息:

assert()

所在头文件:<assert.h>

函数原型:void assert (int expression);

参数:expression即要检测的表达式

返回值:无返回值

assert() 的用法很简单,我们只要传入一个表达式,它会计算这个表达式的结果:如果表达式的结果为"假",assert() 会打印出断言失败的信息,并调用 abort() 函数终止程序的执行;如果表达式的结果为"真",assert() 就什么也不做,程序继续往后执行。

如果想要禁用这个断言函数,只需将

#define NDEBUG

定义在在代码的开头,在包含 <assert.h> 之前。

四,编译习惯很重要

(0)从内存的视角写代码

当我们写代码的时候,我们要有内存意识,看代码是内存,看数组是连续的线性表,如果是局部变量,则创建在栈区,地址先高后低等。

(1)函数的高内聚低耦合

我们写项目,往往需要实现多个功能,这时我们如果把所有的代码写在一起,那么一方面先显得逻辑不清,调试的时候不方便,为自己设置了障碍,另一方面,如果我们又要使用一个函数的某个功能,就又要重新写了。

如果我们将项目封装成一个一个功能不一的函数,在使用的时候调用,这样代码的逻辑性会有很大提高,并且可以减小代码量,提高效率。

(2)要写注释

  1. 解释代码:注释可以用来解释代码的意义和作用,有助于其他开发人员理解你的代码。

  2. 提高代码可读性:注释可以使代码更易读,更具有可读性。通过注释可以使代码更加易于理解,特别是在一些复杂的算法或逻辑代码中。

  3. 方便调试:注释可以用来记录程序的执行流程,这可以帮助错误诊断和调试。

  4. 方便维护:注释可以记录代码的变更历史和维护记录,方便以后维护和修改代码。

  5. 提高代码质量:注释可以强制编写人员思考代码的逻辑,有助于代码的质量提高。

(3)适当留白

适当的留白可以提升代码的可读性,便于理解。

五,想要告诉你

最好的Debug就是减少写出的bug,在写程序之前要根据内存的,数据结构的知识对代码的可行性与逻辑性进行估计,在心里构建出自己的想法的实现方法。

敢于发现并承认自己的错误

Debug是一个反复迭代的过程,需要不断地尝试和测试,直到找到并解决所有的错误。

加油!


编译时报错解决https://blog.csdn.net/2301_79465388/article/details/133919788?spm=1001.2014.3001.5502函数栈帧的创建与销毁https://blog.csdn.net/2301_79465388/article/details/134256464?spm=1001.2014.3001.5502

文章回顾


目录

O,前言

一,什么是bug?

二,什么是Debug

三,通用编译器的Debug

1.打印输出

2.单步调试

3.设置断点

4.监视与内存观察

5.设置断言

四,编译习惯很重要

(0)从内存的视角写代码

(1)函数的高内聚低耦合

(2)要写注释

(3)适当留白

五,想要告诉你


完~

未经作者同意禁止转载

相关推荐
Half-up3 分钟前
C语言心型代码解析
c语言·开发语言
Source.Liu24 分钟前
【用Rust写CAD】第二章 第四节 函数
开发语言·rust
monkey_meng24 分钟前
【Rust中的迭代器】
开发语言·后端·rust
余衫马27 分钟前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng31 分钟前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
Jacob程序员33 分钟前
java导出word文件(手绘)
java·开发语言·word
小白学大数据39 分钟前
正则表达式在Kotlin中的应用:提取图片链接
开发语言·python·selenium·正则表达式·kotlin
VBA633741 分钟前
VBA之Word应用第三章第三节:打开文档,并将文档分配给变量
开发语言
半盏茶香42 分钟前
【C语言】分支和循环详解(下)猜数字游戏
c语言·开发语言·c++·算法·游戏
Jack黄从零学c++1 小时前
C++ 的异常处理详解
c++·经验分享