实用调试技巧

一、什么是bug

第一次被发现的导致计算机错误的飞蛾,也是第一个计算机程序错误。

bug本意是“昆⾍”或“⾍⼦”,现在⼀般是指在电脑系统或程序中,隐藏着的⼀些未被发现的缺陷或 问题,简称程序漏洞。

二、调试是什么?有多重要?

2.1调试是什么

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

2.2调试的基本步骤

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

2.3Debug和Release的介绍

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

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

例如以下代码:

切换Debug和Release版本的结果不同,有可调式和不可调试的区别,而大小也不同,Release版本更加优化

三、Windows环境调试介绍

3.1调试环境准备

在环境中选择Debug选项,才能使代码正常调试

VS2022 - IDE - 集成开发环境 - >编辑器+编译器+调试器

3.2学会快捷键

最常用的几个快捷键:
F5:启动调试,经常用来直接跳到下一个断点处
F9:创建断点和取消断点
断点的重要作用,可以在程序的任意位置设置断点。
这样就可以使得程序在想要的位置随意停止执行,继而一步步执行下去。

F5和F9是配合使用的

(先启动调试,再使用)

也可以跨文件进行

---------------------------------------------------------------------------------------------------------------------------------

F10:逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句。
F11:逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部(这是最常用的)

F10和F11也是配合使用的

(先调试起来)

如果在调试的过程中,只使用了F10,那就看不了函数内部的细节,只会显示ret最终的结果,而不会进入Add函数内部进行观察

如果在调试过程中,加入F11的使用,在走到Add函数时,按F11,将会进入到函数内部,进而可观察到x、y的变化

---------------------------------------------------------------------------------------------------------------------------------

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

(ctrl+fn+f5)

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

我们将会了解学习以下信息:

3.3.1自动窗口

可以动态的观察变量的值,不用自己输入,但是不太方便,因为随着一步一步地走,显示的变量会随着一起变化,不方便观察

3.3.2局部变量

也可以动态的观察变量的变化,不过局部变量不能观察地址的变化,不过和自动变量一样,也不太方便

3.3.3监视

监视是最方便的,可以观察任何的变量,甚至是等式

也可以观察数组的变化:

当进入函数内部时,只能观察到数组内的一个元素,如果想要全部都观察得到,可以这样写:arr,12

3.3.4内存

取出a、b、arr的地址

3.3.5反汇编

可以右击鼠标获得,也可以在调试 - 窗口中找到

(先调试起来)

3.3.6寄存器

如果记得寄存器的名字,也可以使用监视来观察

可以转为十六进制

3.3.7调用堆栈

(右击鼠标,勾选显示外部代码)

与数据结构中的栈、队列相似,每走一步,都要先进行排队,由低到高进行观察,当往回走的时候,又从高处往回走回来(删除)

四、实例

4.1实现代码:求1!+2!+3!+……+n!;不考虑溢出

(本代码为特定的代码,是设计好的,仅在VS2019 X86的环境下适用)

运行起来发现错误

进行调试可知:是ret的定义出了问题:ret始终等于0,这时候我们需要改变,改为1

修改完成并把代码写完整后,输入n=5时,输出的结果是15,是错误的

这时候我们再次进行调试,我们发现是在n=3的时候ret的结果发生错误,通过断点来进一步确认具体的错误

首先设置断点的条件:

进行调试后发现此时的ret变成了2,因此我们应该这样改:在每次进入循环前将ret改成1

这样结果就是正确的了:

4.2研究死循环的原因

运行以下的代码,会进行死循环:

我们通过调试来观察它死循环的原因:

当调试起来一步步走到下表为9的元素时,数组内的所有元素已经被改为了0,而此时循环体还没有结束,继续进行,我们将要观察的arr[10],arr[11],arr[12]单独列出来观察,会发现除了arr[12]外,其他两个都被改为了0,而arr[12]会跟着i的变化而变化

     

当i=12时,arr[12]=12,而下一步i又变为了0,开始进行下一轮的循环,每次一到12时,就会进行下一轮循环,一直死循环下去,arr[12]始终跟着i变化

由于i和arr[12]有这样的关系,我们猜测它们有相同的一个空间,通过对它们地址的观察,发现猜想是正确的

那么为什么会这样呢?

首先我们知道,局部变量是放在内存中的栈区的,而栈区的使用习惯是:先使用高地址处的空间,再使用低地址处的空间;数组随着下标的增长,地址是由低到高变化的

由此,我们结合图片可知:在i和arr数组中间恰好就是两个字节的整型(在VS2019环境下实验的一个结果)

本代码在release版本下可以正常运行,因为release版本已经帮我们优化好了的

此版本中i和arr之间也不再是只有2个整型

如果将i和arr的定义的位置互换,确实就不会发生arr数组与i重叠的情况,但会报警告

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值