该学会是自己找bug了(vs调试技巧)

news2024/9/24 23:24:01

前言

🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨
🐻推荐专栏: 🍔🍟🌯 c语言初阶
🔑个人信条: 🌵知行合一
🍉本篇简介:>:介绍c语言初阶的最后一篇.有关调试的重要性.
金句分享:
✨夜色难免黑凉,前行必有曙光.✨

目录

  • 前言
  • 程序猿们每天都在写bug?
  • 一、调试是什么?
  • 二、两个版本的介绍(Debug和Release)
  • 三、调试的快捷键
  • 四、调试窗口
    • 4.1 监视窗口(查看变量的值)
    • 4.2 自动窗口
    • 4.3 内存窗口
  • 五.编程常见的错误

本篇是c语言初阶的最后一篇,加油!!!

程序猿们每天都在写bug?

bug是什么?
1947 年 9 月 9 日:世界上的第一个“Bug”被发现.
日记:
“1949 年 9 月 9 日,我们晚上调试机器的时候,开着的窗户没有纱窗,机器闪烁的亮光几乎吸引来了世界上所有的虫子。果然机器故障了,我们发现了一只被继电器拍死的飞蛾,翅膀大约 4 英寸。”

格蕾丝·霍普(Grace Hopper)用发夹取出飞蛾,把它粘在日志里,并标注:“First actual case of bug being found”(找到了第一个 Bug)。这件计算机史上的奇闻轶事,使“Bug”作为计算机领域的专用词汇,一直沿用至今。

下图是当时的日记图片:

现在的程序员依旧逃不出“Bug”的魔爪,初学者可能大部分时间在写代码,只有少部分时间在找bug.但是大部分已经工作的程序猿,在工作的一天里,20% 的时间是在写代码,80% 的时间是在找 Bug

讲个笑话:
如果你在一个技术岗位周围听到了一声崩溃的惨叫,不要慌张,这可能是某个程序员找 Bug 找的崩溃了。如果一群程序员同时发出惨叫,那可能是有人把电源线踢掉了。
在这里插入图片描述

一、调试是什么?

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

简单来说,调试就是一个在找bug的过程.

一名优秀的程序员是一名出色的侦探。
如果bug的出现是"犯罪",那么每一次调试都是尝试破案的过程.
一件事情的发生都是有迹可循的,顺着思路写代码出现了bug,这相当于犯罪的过程,逆流而上便是调试的工作,这便是寻找真相的过程.

二、两个版本的介绍(Debug和Release)

Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。

Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。

在这里插入图片描述

观察Debug区别和Release版本的区别:

测试代码:

#include <stdio.h>
int main()
{
	printf("初阶牛,你好!!!\n");
	return 0;
}

当我们运行之后:
观察比较代码运行后形成的.exe文件在硬盘上存放所占字节大小.

Debug版本:
在这里插入图片描述

Release版本:
在这里插入图片描述

上述情况可以证明Release版本会对代码进行各种优化,使得代码大小变小.
Debug版本要保存调试信息,相对占用大小要更大一点.

编译器进行了哪些优化呢?
🌰当我们写出一个数组越界访问的代码时:

#include <stdio.h>
int main()
{
	int i = 0;
	int arr[5] = { 0 };
	for (i = 0; i < 10; i++)//越界访问
	{
		arr[i] = i;
		printf("%d\n", i);
	}
	return 0;
}

Debug版本调试结果:
在这里插入图片描述
Release版本调试结果:
在这里插入图片描述
不难发现,即使数组越界访问,在Release版本直接被优化掉了,并不会产生报错信息.

补充知识:
你用的是什么编译器?
vs2019?或者vs2022?
其实这些准确来说不能成为编译器,vs称为IDE(集成开发环境)
编辑器+编译器+调试器

三、调试的快捷键

调试时,快捷键的使用可以大大提高我们的调试效率,所以熟练的使用快捷键是很有必要的.

F5:启动调试

经常用来直接跳到下一个断点处。如果没有设置断点就会直接运行.

F9:创建断点和取消断点

断点的重要作用,可以在程序的任意位置设置断点。
这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去。

F10:逐过程

通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。,主要用于跳过确定没有问题的函数,不需要进入函数内部一条条语句调试.

F11:逐语句

就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最常用的情况)。

CTRL + F5:开始执行不调试

如果你想让程序直接运行起来而不调试就可以直接使用。

四、调试窗口

4.1 监视窗口(查看变量的值)

F11进入调试状态,单击"调试"选项卡,选择"窗口"命令,在子菜单中选择"监视命令".
四个监视窗口都是一样的,随意选择一个即可.
在这里插入图片描述
在打开的"监视"的窗口中,可以输入想要观察的变量,十分方便,个人是很喜欢vs的调试环境的.推荐使用"监视窗口"观察变量.

请通过调试,观察变量的变化,找出代码出错的地方.
示例:
请用自定义函数的形式编程实现,求s = m!+ n!+ k!,
其中m、n、k从键盘输入(值均小于7)。

#include <stdio.h>
#define Max 7

int Factorial(int m)//计算阶乘的函数
{
	int ret = 0;
	while (m)
	{
		ret *= m;
		m--;
	}
	return ret;
}
int main()
{
	int m = 0, n = 0, k = 0;
	int s = 0;//记录这三个阶乘的和
	printf("请分别输入m,n,k的值:\n");
	scanf("%d%d%d", &m, &n, &k);
	if (m < Max && n < Max && k < Max)
	{
		s=Factorial(m) +Factorial(n) +Factorial(k);//分别调用计算阶乘的函数
		printf("这三个数的阶乘之和是:%d", s);

	}
	else
	{
		printf("很抱歉,你输入的三个数中,有大于7的数.\n");
	}
	return 0;
}

在这里插入图片描述
答案:
出错原因:Factorial函数中,ret初始化为0,出现错误,应当初始化为1,因为0与任何数的乘积都为0;
通过监视窗口,不难发现,ret计算阶乘时值一直为0;

4.2 自动窗口

"监视"窗口,要求自己手动输入需要观察的变量.
自动窗口不需要自己输入观察的变量,会自动出现.
缺点是"自动窗口"中的变量会动态显示,只会显示当前正在操作涉及的部分变量,当进入一个函数时,函数外的变量就观察不到.并不推荐使用

4.3 内存窗口

在这里插入图片描述
在内存窗口中,可以输入想要观察的变量的内存地址,甚至可以细致到每一个字节.
在这里插入图片描述
当然,vs还提供了"调用堆栈",“反汇编”,"寄存器"等多种类型的窗口方便调试,就不一 一介绍了,可以自己去试着调试,观察.

五.编程常见的错误

7.1 编译型错误
编译器会直接标红,例如:

语法错误,
中英文错误
括号不完整等

这类错误很好发现,也能很快的解决,并不是很复杂的错误.根据编程经验就可以解决.
语句后面忘记":"分号

在这里插入图片描述

5.2 链接型错误
编译器会给出错误信息,主要在代码中找到错误信息中的标识符,。一般是标识符名不存在或者拼写错误。这也是不难解决的问题.
在这里插入图片描述
5.3 运行时错误

这是最难解决的的问题,只有在运行时,发现并不是自己想要的结果.
这类问题只能通过调试,一步步解决,当代码比较复杂时,一步步调试会显得特别繁琐,这时可以借助F9创建断点,和F10逐过程(不进入函数内部),跳过部分没有出问题的代码区域,即使是这样,这类问题还是很难得以解决.
在这里插入图片描述

遇见bug不要太难过,也不要过度生气,自己解决就行了,虽然bug的出现让人很头痛,可能几个小时都无法找到原因,但是我们通过调试,在"破案"的过程中,也许也会收获很多,成功"破案"后的喜悦也是很甜的哟!!!

希望各位小伙伴,可以多多尝试调试,这也是一种很重要的能力,提高自己的代码编程能力.

下面是一些可以试着练习调试的代码:
试着找出原因吧!!!

示例1:这段代码是在x86环境下运行

在这里插入图片描述

#include <stdio.h>
int main()
{
    int i = 0;
    int arr[10] = { 0 };
    for (i = 0; i <= 12; i++)
    {
        arr[i] = 0;
        printf("初阶牛加油,加油!!!\n");
    }
    return 0;
}

示例2:输入密码

#include <stdio.h>
#define MAX 3
int main()
{
	char arr1[] = { "初阶牛666" };
	char arr2[20];
	printf("请输入密码:\n");
	int i=MAX;
	while(i)
	{
		printf("你还有%d次机会:",i);
		scanf("%s", arr2);
		if (arr1==arr2)
		{
			printf("密码成功");
			break;
		}
		else printf("密码错误,请重新输入:\n");
		i--;//机会-1
	}
	if(i==0)//如果机会用完了
		printf("\n很遗憾你的机会用完了");
	return 0;
}

在这里插入图片描述

答案:
示例1;
当i=12时,令arr[12]=0,此时i的地址和arr[12]的地址是同一块空间,会将i赋值为0
至于为什么是12,是由编译器决定的.
在这里插入图片描述

示例2:
错误:比较两个字符串不能使用==,调试会发现即使密码输入正确,依旧会显示错误.
解决方法:

if (arr1==arr2)
改成if (strcmp(arr1, arr2)==0)

补充小知识:
strcmp是c语言提供的一种库函数,用于比较两个字符串
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续以下对,直到字符不同或达到终止空字符。

返回值.
小于0第一个不匹配的字符在 str1 中的值低于 str2 中的值
0两个字符串的内容相等
大于0第一个不匹配的字符在 str1 中的值大于在 str2 中的值

代码如下

#include <stdio.h>
#include <string.h>
#define MAX 3
int main()
{
	char arr1[] = { "初阶牛666" };
	char arr2[20];
	printf("请输入密码:\n");
	int i=MAX;
	while(i)
	{
		printf("你还有%d次机会:",i);
		scanf("%s", arr2);
		if (strcmp(arr1, arr2)==0)//判断字符串相等
		{
			printf("密码成功");
			break;
		}
		else printf("密码错误,请重新输入:\n");
		i--;//机会-1
	}
	if(i==0)//如果机会用完了
		printf("\n很遗憾你的机会用完了");
	return 0;
}

到目前为止,c语言初阶的内容就全部更新完成了,感谢大家的支持!!!
后面就是c语言进阶的内容了.
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/367589.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux基本介绍与常用操作指令

参考链接&#xff1a; Linux面试必备20个常用命令_无 羡ღ的博客-CSDN博客_linux常用命令 1. Linux简介 Linux是一个支持多用户、多任务、多线程和多CPU的操作系统&#xff0c;特点是免费、稳定、高效&#xff0c; 一般运行在大型服务器上。 1.1 常用目录简介 /&#xff1a;根目…

【storybook】你需要一款能在独立环境下开发组件并生成可视化控件文档的框架吗?(一)

storybook介绍入门说说用法prop-types.stories.jsx介绍 你肯定用过ant-design或者elemenUI中的一款UI组件库&#xff0c; 你肯定打开过它们的官网&#xff0c; 你是否好奇过&#xff0c;页面上展示的案例&#xff0c; 你为啥可以操作&#xff0c;还能查看源码供你CV?它们是…

Docker之路(6.docker容器数据卷、具名挂载匿名挂载、权限挂载)

1. 什么是容器数据卷 如果数据都在容器中&#xff0c;那么容器删除后&#xff0c;数据就会丢失&#xff01; 所以希望容器的数据能够存到本地 容器之间可以又一个数据共享的技术&#xff01; Docker容器中产生的数据&#xff0c;可以同步到本地&#xff0c;这就是卷技术。 就是…

Nacos Ignore the empty nacos configuration and get it based on dataId

1.配置错误 dataId问题 启动日志&#xff1a; 使用properties格式的文件&#xff1a; Ignore the empty nacos configuration and get it based on dataId[xxx-server] & group[DEFAULT_GROUP] Ignore the empty nacos configuration and get it based on dataId[xxx-s…

【Redis中bigkey你了解吗?bigkey的危害?】

一.Redis中bigkey你了解吗&#xff1f;bigkey的危害&#xff1f; 如果面试官问到了这个问题&#xff0c;不必惊慌&#xff0c;接下来我们从什么是bigkey&#xff1f;bigkey划分的类型&#xff1f;bigkey危害之处&#xff1f; 二.什么是bigkey&#xff1f;会有什么影响&#xff…

九头蛇hydra爆破http示例

使用hydra执行http表单暴力破解 通过浏览器自带分析得知: 提交地址:http://10.0.0.115/student_attendance/ajax.php?action=login 提交方式:POST 提交数据:username=a&password=a 服务响应:3 根据以上收集的信息就可以使用hydra进行密码爆破 hydra 10.0.0.115 http…

【第一章:Spring概述、特点、IOC容器、IOC操作bean管理(基于xml方式创建对象,注入属性)】

第一章&#xff1a;Spring概述、特点、IOC容器、IOC操作bean管理&#xff08;基于xml方式创建对象&#xff0c;注入属性&#xff09; 1.Spring是什么&#xff1f; ①Spring是一款主流的java EE 轻量级开源框架。 ②广义的Spring&#xff1a;Spring技术栈&#xff0c;Spring不再…

华为OD机试题,用 Java 解【计算最大乘积】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

【基础算法】哈希表(开放寻址法)

&#x1f339;作者:云小逸 &#x1f4dd;个人主页:云小逸的主页 &#x1f4dd;Github:云小逸的Github &#x1f91f;motto:要敢于一个人默默的面对自己&#xff0c;强大自己才是核心。不要等到什么都没有了&#xff0c;才下定决心去做。种一颗树&#xff0c;最好的时间是十年前…

聚观早报|饿了么星选停止运营;百度2022财报全年营收1236.75亿元

今日要闻&#xff1a;饿了么星选停止运营&#xff1b;百度2022财报全年营收1236.75亿元&#xff1b;微软收购暴雪获力挺&#xff1b;全国首例&#xff01;这一代练平台被叫停&#xff1b;现代汽车已开始在美国生产电动汽车 饿了么星选停止运营 2 月 22 日&#xff0c;饿了么旗下…

使用Vite创建VUE项目

使用Vite来创建vue项目 很久没有接触前端的技术了&#xff0c;一下子就冒出来很多技术&#xff0c;有的根本没见过呀&#xff0c;vue变成了3&#xff0c;vue-cli也变得不好用了&#xff0c;说vite很好用&#xff0c;那就创建个项目试试吧。 有一点前提哈&#xff0c;电脑上要…

华为OD机试题,用 Java 解【磁盘容量排序】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

【100个 Unity实用技能】 | 将Dictionary字典中的数据序列化 到Unity Inspector监视器面板

Unity 小科普 老规矩&#xff0c;先介绍一下 Unity 的科普小知识&#xff1a; Unity是 实时3D互动内容创作和运营平台 。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者&#xff0c;借助 Unity 将创意变成现实。Unity 平台提供一整套完善的软件解决方案&#xff…

【vue2每日小知识】实现store中modules模块的封装与自动导入

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;省去我们store仓库中分模块时的需要每次导入index的问题 目录 【前言】在store中如何简…

UART 串口通信实验

目录 一、UART 简介 1、 UART 通信格式 二、I.MX6U UART 简介 1、硬件原理 2、寄存器 UARTx_UCR1(x1~8) UARTx_UCR2​ UARTx_UCR3​ UARTx_USR2​ 其他寄存器 三、代码编写 1、编写bsp_uart.h 2、编写bsp_uart.c 3、main 不管是单片机开发还是嵌入式 Linux 开发&a…

Kubernetes入门教程 --- 使用kubeadm进行集群安装

Kubernetes入门教程 --- 使用kubeadm和二进制安装1. Introduction1.1 架构图1.2 关键字介绍1.3 简述2. 使用Kubeadm Install2.1 申请三个虚拟环境2.2 准备安装环境2.3 配置yum源2.4 安装Docker2.5 时间同步2.6 安装组件2.7 部署集群2.8 Master安装网络插卡3. 查询状态3.1 查询n…

【数据库】一文讲清redis的主从复制

目录 主从复制 一&#xff0c; 主从复制原理 二&#xff0c;主从复制配置 1&#xff0c;一主双从 1、配置三个redis示例 2、配置主从 3、集群测试 2&#xff0c; 主从切换 哨兵模式 一&#xff0c; 什么是哨兵模式 二&#xff0c; 配置哨兵 三&#xff0c;启动哨兵 …

公网远程连接Oracle数据库【内网穿透】

文章目录1. 数据库搭建2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射3. 公网远程访问4. 配置固定TCP端口地址4.1 保留一个固定的公网TCP端口地址4.2 配置固定公网TCP端口地址4.3 测试使用固定TCP端口地址远程OracleOracle&#xff0c;是甲骨文公司的一款关系数据库管理系…

阅读笔记8——NMS

一、基本NMS 1. 处理过程 为了保证物体检测的召回率&#xff0c;对于同一个真实物体往往会有多于1个的候选框输出。但是多余的候选框会影响检测精度&#xff0c;因此需要利用NMS过滤掉重叠的候选框&#xff0c;基本的NMS方法利用得分高的边框抑制得分低且重叠程度高的边框。 如…

追梦之旅【数据结构篇】——详解C语言实现链栈

详解C语言实现链栈~&#x1f60e;前言&#x1f64c;整体实现内容分析&#x1f49e;1.头文件编码实现&#x1f64c;2.功能文件编码实现&#x1f64c;3.测试函数功能代码&#x1f64c;总结撒花&#x1f49e;&#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的座右…