实用调试技巧(1)

news2024/10/6 18:20:32

在这里插入图片描述

  • 什么是bug?
  • 调试是什么?有多重要?
  • debug和release的介绍。
  • windows环境调试介绍。
  • 一些调试的实例。
  • 如何写出好(易于调试)的代码。
  • 编程常见的错误。

什么是Bug
我们在写代码的时候遇到的一些问题而导致程序出问题的就是Bug,世界上的第一个Bug是一支飞蛾,这就是Bug的由来,在早期的时候,机器突然坏了,工作人员进行检查,最后发现是一只飞蛾导致机器故障,所以也有了现在的Bug之称。
在这里插入图片描述

当天的工作人员将他贴在了笔记本上,这就是时间上的第一个Bug。
调试是什么
我们在初学的时候会遇到各种各样的问题,这个时候我们就需要进行调试,这样才能解决Bug,所以调试非常重要,一个出色的程序员必须会调试

所有发生的事情都一定有迹可循,如果问心无愧,就不需要掩盖也就没有迹象了,如果问心有愧,就必然需要掩盖,那就一定会有迹象,迹象越多就越容易顺藤而上,这就是推理的途径。
顺着这条途径顺流而下就是犯罪,逆流而上,就是真相。

但是我们在初学的时候总是盲目的调试,可能只是简单摁下键盘上的F10,调试一直到我们代码结束的时候,只是走了一遍流程,却不知道问题在哪里,这就是我们初学者经常出现的问题。
所以我们要拒绝迷信调试,要真正的找到问题所在,解决这个臭虫

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

2.2 调试的基本步骤

  • 发现程序错误的存在
  • 以隔离、消除等方式对错误进行定位
  • 确定错误产生的原因
  • 提出纠正错误的解决办法
  • 对程序错误予以改正,重新测试

而我们写程序的时候出现Bug生活中一般有三种人,一是程序员自己,二是测试员,三是用户。
测试员就是相当于你写的代码经过relase之后到测试员那里,它进行测试。

3 Debug和Release的介绍

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

就是相当于我们平常在编译器上写的代码

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

这个就是我们的代码经过优化后呈现给用户的

那我们用代码给大家演示一下他们有什么不一样的地方

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6 };
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		arr[i] = -1;
	}
	for (i = 0; i < 10; i++)
	{

		printf("%d ", arr[i]);
	}
	return 0;
}

在这里插入图片描述
上面就是我们在Debug和release下生成的可执行文件

在这里插入图片描述
在这里插入图片描述
很明显Release下的内存明显小了很多,说名它进行过优化,我们这是在X86平台下,就是32位机器下,当然我们改成X64也是一样的道理

在这里插入图片描述

在这里插入图片描述
3. Windows环境调试介绍
那我们在了解环境之前先要来了解一些东西,比如就是快捷键,何为快捷键,就是让你变得快捷起来。

在这里插入图片描述
在我们的调试里头就有这些快捷键,来介绍几个常用的
CTRL + F5

这个键就是我们每次运行要得到我们的结果的时候用的,它的意思就是开始执行不调试,直接运行程序。

F11

这个就是一条一条语句往下执行,我们在调试过程中这是必然不可缺少的,它也可以进到我们的函数当中去。

F10

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

F10和F11其实差不多,就是后者更细致一点,作用都是差不多的。

F9

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

F5

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

下面举例子给大家看看断点有多方便。

在这里插入图片描述

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6 };
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		arr[i] = -1;
	}
	for (i = 0; i < 10; i++)
	{

		printf("%d ", arr[i]);
	}
	printf("\n");
	for (i = 0; i < 10; i++)
	{
		printf("hehe\n");
	}
	return 0;
}

我们在上面设置了一个断点,并且条件是i==6,那让我们按下F5看看吧。
在这里插入图片描述
上面我只按了一个F5就到了,可是如果我按F10,要经过一个半的for循环,有时候按的快的时候,一下子按过头了又要重新按(小编一开始就是这么蠢,大家学聪明点),可见断点和F5连用是这么方便。
在这里插入图片描述
同时屏幕上也打印了6个-1
还有其他相当多的快捷键大家也可以去网上找找,增加对VS的理解

会快捷键之后我们还需要学习一些其他的,往下看
3.3 调试的时候查看程序当前信息
在这里插入图片描述

在窗口里有各式各样的好东西,让我们来看看吧
当然我们这些窗口必须是要开始调试起来的时候才能看到,我一开始学的时候,不知道这个,废了好大劲才找到我原来都没有开始调试。
监视窗口
在这里插入图片描述
任意选一个都可以,在这里我们就可以输入我们想要监视的,比如数组名,还有数组的元素,一些变量,我们都可以看到它时刻的值,当然大家也可以看到自动窗口和局部变量,这些也都是监视的,只不过它是自己生成的,虽然很方便但是它有时候会自己变值,总的来说还是不便于观察,我们在学得时候,小编建议大家还是自己尝试,这样才能提升自己的调试技巧。
内存窗口
这个也很重要,我们在栈上创建变量的时候,都是占用空间的,而我们会用相应的编号找到他们的位置,这也是让我们更好的观察他们,让我们更容易调试,找到Bug。

3.3 查看调用堆栈

调用堆栈主要是反映逻辑关系,比如我们过多的调用函数的时候不明白它的逻辑的时候可以使用

举个例子

#include<stdio.h>
void test1()
{
	printf("hehe\n");
}
void test()
{
	test1();
}
int main()
{
	test();
	return 0;
}

在这里插入图片描述
我们返回的时候是下面这样
在这里插入图片描述
啥意思呢,就是我们之前讲过函数栈帧一样,栈是一步一步在顶上开辟,然后一步一步返回的。

3.4 查看汇编信息

在这里插入图片描述
在函数栈帧讲过,建议大家去看一下
3.5 查看寄存器信息
在这里插入图片描述
之前讲过esp和ebp还有edi这些,他们的作用都是一样,存储数据,其中ebp和esp有维护函数栈帧的作用。

接下来给两个例子给大家调试一下看,不过都是最基础的调试.

实例

实现代码:求 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;
}

我们的代码主要是为了计算阶乘的大小,前几个阶乘相加计算出结果,但是我们上面的代码其实是有问题的,我们一步一步调试来看看,首先我们要写出我们每次心里想的结果去对比编译器中监视进行对比,找出问题。
在这里插入图片描述
在这里插入图片描述

调试之前可以像我一样把要观察的写出来

在这里插入图片描述
j循环的for语句执行一次,因为i=1,算出1的阶乘,答案是对的。
我们看2的阶乘
在这里插入图片描述

在这里插入图片描述
其实我们在这里就能看出结果,原因是我们是在原来的基础性上阶乘,但是运气好,答案是对的,当我们继续往下走,就会看出端倪

在这里插入图片描述
一看和我们预想的有问题,这时候就要警惕,如果我们第一次没看出来,但是结果不一样,这时候就要小心了,不过很显然,为什么造成这个原因,我们在调试过程一看就才可以看出来了,ret一直是在原来基础上改变,所以我们给他进入循环的时候变成1就可以了。

改正

#include<stdio.h>

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;
		ret = 1;
		for (j = 1; j <= i; j++)
		{
			ret *= j;
		}
		sum += ret;
	}
	printf("%d\n", sum);
	return 0;
}

实例two

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

想要解释这道题必须调试才能知道
给个前提,必须在VS这个编译器下,而且是X86,Debug下,别的一些编译器也行,但还是有点初入,这里我们不进行调试是做不出来,下面调试。

在这里插入图片描述

当我们的i变成9的时候,刚刚把原始数组都赋值为0

在这里插入图片描述
很神奇,我们数组下标到9就应该结束,但是现在竟然把arr[10]的内容赋值为0,我们语句越界访问了

在这里插入图片描述
11也是,i还在变大
在这里插入图片描述
arr[12]怎么放的是i的值,好奇怪,我们继续往下。
在这里插入图片描述

i突然变成0了,arr[12]的内容也是0,说明赋值成功,但是i又变了。我们就要去怀疑他们是不是公用一个空间

在这里插入图片描述
结果一看还真是,那就说明arr[12]和i用的是一个地址,后来i又变成0了,所以才会死循环,讲到这里大家肯定明白了把


在这里插入图片描述
说面我们arr数组开辟的时候和i中间差两个整型,我们数组的下标是由低地址到高地址的

今天我们先讲一部分调试技巧,内容太多了,小编写不动了,谢谢大家!!!

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

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

相关文章

C语言——函数栈帧的创建和销毁

Hello&#xff0c;好久没有写博客了&#xff0c;前两份都是之前写的&#xff0c;看来最近有点懈怠&#xff0c;最近也得快点找回学习的状态&#xff0c;那今天开始我们新的讲解 在我们刚开始学习C语言的时候&#xff0c;不知道大家有没有困惑&#xff0c;比如我们在使用局部变量…

vue 表单form-item模板(编辑,查看,新建)

目录 formatFormData 后端数据格式​编辑 JSON解析和生成 加载&#xff08;请求前&#xff0c;await后&#xff09; formComp formatFormData 后端数据格式 为空的&#xff0c;可以直接不提交/提交null/undefined JSON解析和生成 var str {"name": "…

ERROR: No matching distribution found for wxpyhton

ERROR: No matching distribution found for wxpyhton pip install 库包名 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.compip install wxpython -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

Voicebox:文本引导的大规模多语言通用语音生成

说白了就是录一段你的声音&#xff0c;在最短的时间内学会你说话&#xff01; Meta AI研究团队模型&#xff0c;Voicebox是一个文本转语音的工具&#xff0c;具有多种功能和应用。根据提供的搜索结果&#xff0c;以下是Voicebox的一些功能和特点&#xff1a; 多语言支持&…

语义分割、转置卷积、风格迁移(第十二次组会)

TOC 语义分割 图像分割、实例分割 上采样、下采样 转置卷积 全卷积网络 风格迁移

操作系统_进程与线程(四)

目录 4. 死锁 4.1 死锁的概念 4.1.1 死锁的定义 4.1.2 死锁产生的原因 4.1.3 死锁的处理策略 4.2 死锁预防 4.3 死锁避免 4.3.1 系统安全状态 4.3.2 银行家算法 4.3.2.1 数据结构描述 4.3.2.2 银行家算法描述 4.3.2.3 安全性算法 4.3.3 安全性算法举例 4.3.4 银行…

【EI/SCOPUS会议征稿】第三届物联网与机器学习国际学术会议(IoTML 2023)

第三届物联网与机器学习国际学术会议&#xff08;IoTML 2023&#xff09; 2023 3rd International Conference on Internet of Things and Machine Learning 2023年物联网与机器学习国际学术会议&#xff08;IoTML 2023&#xff09;将于2023年9月15-17日在新加坡召开。会议…

安装华为模拟器

安装前需要安装虚拟机 虚拟机安装 下一步 立即安装 安装驱动 完成 一路下一步 安装完成后拖动一个2240启动

【Liux下6818开发板(ARM)】实现简易相册

(꒪ꇴ꒪ ),hello我是祐言博客主页&#xff1a;C语言基础,Linux基础,软件配置领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff01;送给读者的一句鸡汤&#x1f914;&#xff1a;集中起来的意志可以击穿顽石!作者水平很有限&#xff0c;如果发现错误&#x…

Linux NameSpace 虚拟化 资源隔离

NameSpace NameSpace介绍 在操作系统中命名空间命名空间提供的是系统资源的隔离&#xff0c;其中系统资源包括了&#xff1a;进程、网络、文件系统等等 实际上linux系统实现命名空间主要目的之一就是为了实现轻量级虚拟化服务&#xff0c;也就是我们说的容器&#xff0c;在同…

分享一个赛车动画

先看效果&#xff08;动画太大了放不上来&#xff0c;甘心去复制代码运行即可&#xff09;&#xff1a; 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>赛车</title><…

AD21 PCB设计的高级应用(六)极坐标的应用

&#xff08;六&#xff09;极坐标的应用 在 PCB 设计过程中,特别是 LED圆形灯板的 PCB 设计,需要对 LED灯珠进行圆形等间距排列,如果每个元件都计算清楚其坐标再进行放置会非常烦琐。要实现如图 所示的元件布局效果,在 Altium Designer 软件里可以使用极坐标的方法。 (1)打开…

Vue2 第十一节 Vue的生命周期

1.生命周期的概念 2.生命周期流程图 3.生命周期分析 一.生命周期概念 生命周期又称为生命周期回调函数&#xff0c;生命周期函数&#xff0c;生命周期钩子是Vue在关键时刻帮我们调用的一些特殊名称的函数生命周期函数的名字不可更改&#xff0c;但函数的具体内容是程序员根…

【低代码开发】:加速应用开发的未来趋势

低代码开发&#xff1a;加速应用开发的未来趋势 引言什么是低代码以及功能特点&#xff1f;什么是低代码开发&#xff1f;低代码平台的特点和功能低代码平台的应用场景和优势低代码的优点低代码的缺点低代码平台项目开发流程选择和实施低代码平台 低代码未来的发展趋势低代码平…

MyBatis缓存-提高检索效率的利器--一级缓存

&#x1f600;前言 本篇博文是关于MyBatis一级缓存的介绍使用和缓存失效情况分析&#xff0c;希望能够帮助到您&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家…

c++基础知识(inline、auto、nullptr)

⭐️ 内联函数 &#x1f4ac; 为什么会有内联函数&#xff1f;   内联函数其实是为了弥补 c 的缺陷&#xff0c;比如当我们遇到了一些少量逻辑和代码的情况时&#xff0c;而这些少量的代码又需要被重复使用多次&#xff08;swap&#xff09;&#xff0c;我们往往会封装成为一…

linux快速安装tomcat

linux快速安装tomcat 前提安装好jdk 下载Tomcat安装包 wget https://dlcdn.apache.org/tomcat/tomcat-10/v10.0.27/bin/apache-tomcat-10.0.27.tar.gz如果出现颁发的证书已经过期的错误提示,用下面命令 wget --no-check-certificate https://dlcdn.apache.org/tomcat/tomcat-1…

剑指 Offer 第二版

剑指 Offer 第二版 文章目录 剑指 Offer 第二版[剑指 Offer 06. 从尾到头打印链表](https://www.nowcoder.com/practice/d0267f7f55b3412ba93bd35cfa8e8035?tpId13&tqId23278&ru/exam/oj/ta&qru/ta/coding-interviews/question-ranking&sourceUrl%2Fexam%2Foj…

区块链实验室(13) - 在PBFT中节点的度与其流量的特征

前面若干实验说明了PBFT的耗时、流量与度的特征&#xff0c;见 区块链实验室(10) - 实例说明PBFT的共识过程, 区块链实验室(11) - PBFT耗时与流量特征, 区块链实验室(12) - 网络拓扑对PBFT共识流量的影响 同样的实验方案&#xff0c;在100个节点构成的无标度网络中完成100次交…

html学习4(区块、布局)

1、<div> 是块级元素&#xff0c;它独占一行&#xff0c;可以设置宽度、高度以及边距等样式属性。它适合用于创建页面的大块结构&#xff0c;例如页面的主体区域、容器、布局等。 2、<span> 是行内元素&#xff0c;它不会独占一行&#xff0c;宽度默认由其内容决定…