当程序遇上困难:程序调试的艺术(VS)

简介: 当程序遇上困难:程序调试的艺术(VS)

前言

程序调试,是每个程序员在开发过程中都会遇到的必经之路,今天将分享一些实用的调试技巧,来修炼我们内功,拥有好的内功可以让我们的编程更加得心应手哦·。


一、什么是bug?

Bug是指在程序或系统中存在的错误或缺陷。它可能导致程序无法按照预期的方式运行或产生意外的结果。Bug可以是由编程错误、逻辑错误、算法问题、外部环境变化等引起的。当程序员在开发过程中遇到bug时,他们需要通过调试来定位和修复这些问题,以确保程序的正确性和稳定性。

编程常见的错误

常见的错误分类:

编译型错误

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

链接型错误

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

不存在或者拼写错误。

运行时错误

也就是程序运行时逻辑上的错误。此类错误纠正最为麻烦。

借助调试,逐步定位问题。最难搞

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

所有发生的事都一定有迹可循,如果问心无愧,就不需要掩盖也就没有迹象了,如果问心有

愧,就必然需要掩盖,那就一定会有迹象,迹象越多就越容易顺藤而上,这就是推理的途径。顺着这条途径逆流而上,就是真相。所以每一个合格的程序员都是一名出色的侦探。

想必许多初学者在日常敲代码的过程中都会遇到程序可以运行但不是自己预期结果的情况,遇到这种情况怎么办呢?大多数人估计都是一行一行的去检查逻辑,然后去猜错误的位置,不容易准确定位到错误位置。那么学会调试,就可以很好的解决这个问题,帮助你更快的锁定错误位置。

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

调试的基本步骤

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

Debug和Release

我们在日常使用编译器时,编译器顶部都会有这样的选项:

它们有什么不同呢?

它们在可执行的文件上也有所不同:

Release版本下执行产生的可执行文件:

Debug版本下:

我们会发现它们两个产生的可执行文件的大小有着不小的差距,Debug版本为调试版本,里边包含了所以的调试信息,而Release版本为发布版本,代码在系统上运行时会做一定的优化,所占内存也会更小。

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

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

此外要特别注意,在Release版本下是无法进行程序调试的。

这里不再对两个版本不同进行详细介绍。

三、windows环境调试介绍

我们要想调试一个程序,必须要是处于Debug的版本下才可以进行调试。

学会使用快捷键进行调试

最常使用的几个快捷键:

F5

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

F9

创建断点和取消断点 断点的重要作用,可以在程序的任意位置设置断点。这样就可以使得程序在

想要的位置随意停止执行,继而一步步执行下去。

F10

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

F11

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

最长用的)。

CTRL + F5

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

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

调试查看临时变量的值

当然我们也可以通过调试来查看当先变量的值,可以先按F10或F11先让程序进入调试的状态下,然后在调试功能的里找到窗口,在窗口的选项里找到监视(只有在调试状态下打开窗口才有),就可以弹出监视栏。

输入想要查看当前变量的名字就可以查看到此时变量的数值。

查看调用堆栈

在窗口里找到调用堆栈选项。

通过调用堆栈,可以清晰的反应函数的调用关系以及当前调用所处的位置。

 

调试示例练习

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

这段代码输入3我们期望的输出值是9,而实际输出是15,大家可以通过调试来寻找错误。

示例答案

在程序运行过程中,每次i变化循环都需要将ret初始化为1,上述代码由于未将ret及时初始化为1,导致i=3时,ret的值为2,循环结束后ret的值变为12(2*1*2*3)。1+2+12的值就等于15了。


总结

本期先讲介绍都只是一些简单调试技巧,在后边我们会遇到更复杂的调试情况。使用快捷键可以提高我们的调试效率。

对于初学者来说可能80%的时间在写代码,20%的时间在调试。但是一个程序员可能20%的时间在写程序,但是80%的时间在调试。

在私下里要多多动手,尝试调试,才能有进步哦。好的本期内容到此结束,感谢阅读!

相关文章
|
6月前
|
设计模式 算法 程序员
程序员为何需要反复修改Bug?探寻代码编写中的挑战与现实
作为开发者,我们在日常开发过程中,往往会遇到反复修改bug的情况,而且不能一次性把代码写的完美无瑕,其实开发项目是一项复杂而富有挑战性的任务,即使经验丰富的程序员也难以在一次性编写完美无瑕地完成代码,我个人觉得一次性写好代码是不可能完成的事情。虽然在设计之初已经尽力思考全面,并在实际操作中力求精确,但程序员仍然需要花费大量时间和精力来调试和修复Bug。那么本文就来分享程序员需要反复修改Bug的原因,以及在开发中所面临的复杂性与挑战。
166 1
程序员为何需要反复修改Bug?探寻代码编写中的挑战与现实
|
3月前
|
NoSQL 编译器 程序员
【C语言】揭秘GCC:从平凡到卓越的编译艺术,一场代码与效率的激情碰撞,探索那些不为人知的秘密武器,让你的程序瞬间提速百倍!
【8月更文挑战第20天】GCC,GNU Compiler Collection,是GNU项目中的开源编译器集合,支持C、C++等多种语言。作为C语言程序员的重要工具,GCC具备跨平台性、高度可配置性及丰富的优化选项等特点。通过简单示例,如编译“Hello, GCC!”程序 (`gcc -o hello hello.c`),展示了GCC的基础用法及不同优化级别(`-O0`, `-O1`, `-O3`)对性能的影响。GCC还支持生成调试信息(`-g`),便于使用GDB等工具进行调试。尽管有如Microsoft Visual C++、Clang等竞品,GCC仍因其灵活性和强大的功能被广泛采用。
118 1
|
3月前
|
NoSQL 前端开发 程序员
【震撼揭秘!】程序员绝不会告诉你的秘密:掌握汇编语言调试,轻松从软件故障中全身而退——透视代码底层,成为Bug猎人!
【8月更文挑战第31天】《调试的艺术:如何利用汇编语言追踪和解决软件问题》探讨了使用汇编语言进行高效调试的方法。无论是初学者还是资深开发者,面对棘手的 bug 时,高级语言的信息往往不足。文章通过具体示例展示如何通过汇编代码定位问题,如 C 语言中数组求和函数的崩溃问题。借助 `gcc -S` 生成的汇编代码和 GDB 调试器,可以深入理解程序行为,从而更准确地解决问题。掌握这一技能,将使你在复杂问题面前更加从容。
41 2
|
5月前
|
存储 缓存 NoSQL
不扒瞎,这个程序让我从150s优化到了5s
在优化一个业务开发组的生产问题时,发现销售管理系统查询数据延迟高达2-3分钟。问题根源在于,程序在for循环中频繁读取Redis大KEY数据,导致性能下降。解决方案是采用本地缓存HutoolCache,将耗时降至毫秒级别。此外,还对RedisTemplate配置进行了研究,Jackson2JsonRedisSerializer在序列化时包括了所有字段,即使字段值为null,增加了数据体积。通过对ObjectMapper的调整,仅序列化非空字段,可以显著提升redis读取性能。本文同时还提醒我们在使用Redis时要注意大对象缓存,强调了正确使用和配置缓存以及避免大对象存储的重要性。
64 5
|
6月前
|
程序员 Python
救命!揭秘编程语言中被低估的神器——IF语句
救命!揭秘编程语言中被低估的神器——IF语句
38 2
|
6月前
|
IDE 安全 程序员
揭秘如何用C编写出无敌的程序代码,你绝对会后悔错过!
揭秘如何用C编写出无敌的程序代码,你绝对会后悔错过!
36 1
|
6月前
|
程序员 Python
揭秘单步调试:掌握这一技能让你代码无懈可击
揭秘单步调试:掌握这一技能让你代码无懈可击
51 0
|
存储 程序员 编译器
【C/调试实用技巧】—作为程序员应如何面对并尝试解决Bug?
【C/调试实用技巧】—作为程序员应如何面对并尝试解决Bug?
145 0
|
程序员 编译器 C语言
程序员内功心法之程序环境和预处理(2)
程序员内功心法之程序环境和预处理(2)
164 0
程序员内功心法之程序环境和预处理(2)
|
存储 自然语言处理 编译器
程序员内功心法之程序环境和预处理(1)
程序员内功心法之程序环境和预处理(1)
132 0
程序员内功心法之程序环境和预处理(1)