c语言学习(调试技巧)

什么是bug?

bug原本代表臭虫的意思

后来也指就是计算机程序上锁出现的缺陷

这还得从历史的一次事件中说起

格蕾丝·赫柏(Grace Murray Hopper)是“Bug”的创始人,是一位为美国海军工作的电脑专家,也是最早将人类语言融入到电脑程序的人之一。而代表电脑程序出错的“bug” 这名字,正是由赫柏所取的。1947年9月9日,赫柏对Harvard Mark II设置好17000个继电器进行编程后,这种计算机是依靠控制电流来改变开关,从而实现控制,但是它会发出大量的热和光。技术人员正在进行整机运行时一只飞蛾被计算机的光和热吸引,触发了电脑的短路,,这使得它突然停止了工作。当他们去寻找原因的时候,发现这台巨大的计算机内部一组继电器的触点之间有一只飞蛾,这显然是由于飞蛾受光和热的吸引,飞到了触点上,然后被高电压击死。所以在报告中,赫柏用胶条贴上飞蛾,把它写进了实验报告中,并把“bug”来表示“一个在电脑程序里的错误”,这使得“Bug”这个说法一直沿用到今天

调试是什么?有多重要?

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

调试可以使得我们更加容易的找到错误,从而改正错误

调试的基本步骤

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

Debug和Release的介绍

  • Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序
  • Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用

注:

1、release版本的程序大小比debug版本的小,因为debug包含了调试的工具

2、在release版本的程序不能执行调试,因为缺少了调试的工具

调试环境的准备

调试和发布版本

在vs的这个位置我们可以看到,在这里我们可以改成调试或者发布版本

调试快捷键

我们调试界面,我们发现窗口里面没有监视等其他调试界面

 这是因为我们需要先调试起来才能看到这些窗口

 这个时候我们就会发现出现了这些快捷键

常用的调试快捷键

F5

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

当我们按F5的时候,启动调试的时候箭头就会跳到这个间断点

 这样的话可以使程序直接跳到我们想调试的地方不用一个语句一个语句的进行调试


F9

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


当我们将光标放到此处 按下F9,就会出现一个红色的断点
|
当然我们也可以直接点击左边黑边处


当我们右击鼠标的时候,我们可以对断点进行条件编辑

我们可以通过条件编辑设计一个条件,可以使断点在固定的条件下调试停止
这在循环中很有用,假如我们有个代码,循环很多次

for (int i = 1; i < 10000; i++)
	{
		printf("%d", i);
	}

 我们想要观察i==2000时候的状态,我们可以设置断点的条件为i==2000,这个时候当i==2000时,调剂就会在这个时候停下来

F10

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

当我们按F10时候,程序就会一条一条语句的进行调试,但是不能进入函数内部


F11

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

F11和F10差不多,但是当我们调用函数的时候,我们按F11,这个时候我们就可以进入函数内部


CTRL + F5

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

当我们按ctrl+F5时候,虽然我们设置了间断点,但是程序不会在间断点停止会直接运行

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

查看临时变量的值

四个监视窗口给我们使用,我们可以在里面输入我们想调试的变量

监视器监视的是变量

 除了监视还有自动窗口和局部变量

可以随着调试的进度自动更换里面监视的变量
 

查看内存信息

我们可以在调试-窗口-内存中来查看内存的信息,可以提供我们查看内存信息的窗口也有4个

我们可以通过&a来观察a在内次你中的地址和存储的信息

 查看调用堆

我们可以通过窗口-调用堆栈进行查看
可以看到堆栈的使用情况

 查看汇编信息

 有两种方式

1、通过鼠标右击,再点击转到反汇编

 2、调试-窗口-反汇编
 
就可以看到汇编状态下的情况

查看寄存器信息

 调试-窗口-寄存器可以查看当前运行环境的寄存器的使用信息

调试案例

我们在vs2019环境下编译这段代码

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

发现陷入了死循环通过监视我们发现

数组进行了越界访问,当进行到arr[12]时候我们发现arr[12]与i的值竟然一样,这是为什么呢?
是因为数组越界访问到了i的地址,并改变了i的地址的值再执行一步的时候,i=0,所以变成了死循环

我们了解一下栈区的使用方法(注意栈区和数据结构的栈不是一个概念)

栈区内存使用的习惯是:

先使用高地址的空间,再使用低地址的空间

数组的地址随着下标的增长由低到高增长

当我们访问到a[12]的时候,数组越界了三个地址,a[12]的地址和i相同,所以两个的值都更改了

注:为什么这个时候程序没有报错?
因为程序陷入死循环,报错需要死循环结束才能报错

如何写出好(易于调试)的代码

优秀的代码:
1. 代码运行正常
2. bug很少
3. 效率高
4. 可读性高
5. 可维护性高
6. 注释清晰
7. 文档齐全
常见的coding技巧:
1. 使用assert(调试)
2. 尽量使用const(const修饰的变量只可读不可以修改)
3. 养成良好的编码风格
4. 添加必要的注释
5. 避免编码的陷阱

编程常见的错误

编译型错误

直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定,相对来说简单

 链接型错误

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

运行时错误 

借助我们学过的调试技巧调试,逐步定位问题,最终发现问题所在

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一起慢慢变强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值