0
点赞
收藏
分享

微信扫一扫

【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。




大家好,我是安然无虞。




文章目录

  • 每篇前言
  • ​​一、什么是bug?​​
  • ​​二、拒绝迷信式调试​​
  • ​​1.调试是什么?​​
  • ​​2.调试的基本步骤​​
  • ​​3.Debug和Release的介绍​​
  • ​​三、学会使用快捷键​​
  • ​​四、调试时查看当前程序信息​​
  • ​​1.查看临时变量的值​​
  • ​​2.查看监视信息​​
  • ​​3.查看内存信息​​
  • ​​4.查看汇编信息​​
  • ​​5.查看寄存器信息​​
  • ​​6.查看函数调用堆栈​​
  • ​​五、多动手去调试,才能有进步​​
  • ​​六、经典的调试实例​​
  • ​​实例一:1!+2!+...+n!​​
  • ​​实例二:nice公司的笔试题​​
  • ​​七、如何写好代码·易于调试的代码​​
  • ​​1.优秀的代码​​
  • ​​2.代码示范​​
  • ​​3.const的作用​​
  • ​​七、编程常见的错误​​
  • ​​1.编译型错误​​
  • ​​2.链接性错误​​
  • ​​3.运行时错误​​
  • ​​遇见安然遇见你,不负代码不负卿。​​

每篇前言

作者:安然无虞

作者请求:由于博主水平有限,难免会有错误和不准之处,我也非常渴望知道这些错误,恳请铁汁批评斧正。

【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端


【声明部分】


这是一篇关于实用调试技巧的文章,觉得很实用,所以经过反复学习,终于是将这块内容给整理出来了,我保证不会浪费老铁的时间,这篇博文绝对能让你收获到一些东西的哦。


一、什么是bug?


首先讲一个小故事:
在上个世纪四十年代发现了第一个bug,整个团队都搞不清楚为什么电脑不能正常运作了。经过大家的不懈努力,深度挖掘,发现原来是一只飞蛾意外飞入了一台电脑内部,死在了晶体管上而引起了故障。这个团队将飞蛾尸体清除了之后便排除错误,并在日志本中记录下了这一事件。也因此,人们逐渐开始用“Bug”(原意为“虫子”)来称呼计算机中的程序错误。【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_程序错误_02所以,第一次被发现的导致计算机错误的飞蛾,也是第一个计算机程序错误。



二、拒绝迷信式调试


生活中所有发生的事都一定有迹可循,如果问心无愧,就不需要掩盖也就没有迹象了,如果问心有愧,就必然需要掩盖,那就一定会有迹象,迹象越多就越容易顺藤而上,这就是推理的途径。
沿着这条途径顺流而下就是犯罪,逆流而上就是真相。所以,一名优秀的程序员是一名出色的侦探,每一次调试都是尝试破案的过程。

看看一开始我们是如何写代码的?
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_快捷键_03一开始我们又是如何排查错误的呢?
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_c语言_04哈哈,是不是很真实,感觉这就是以前的我啊!所以,拒绝迷信式调试,这也就是我为什么准备这篇文章肝了这么长的时间。


1.调试是什么?


所谓调试(英文:Debugging/Debug),又叫除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。
正常有三个群体可以发现程序错误:

  • 程序员
  • 测试开发人员
  • 用户

但是当用户发现bug的时候就有一定的风险了,为什么这样说呢,如果是付费软件,出现程序错误会给用户带来损失,那么谁来担这个责任呢?所以,好好学习实用调试技巧这块内容是多么重要。包括后面学习数据结构,必须要掌握这块内容,不然没法学好。


2.调试的基本步骤

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

3.Debug和Release的介绍


Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序,所以,想调试代码,一定要使用Debug版本;
Release称为发布版本,它往往进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用,通常我们所熟悉的测试人员测的就是发布版本,但是请注意,发布版本不能调试。
特别强调:
Debug版本:可以调试
Release版本:不可以调试
为什么所Debug不作任何优化,而Release版本进行了各种优化呢,这里就简单拿文件大小来说明一下,之后再补充详细说明,对于同样的一段程序,Debug文件和Release文件的大小差异还是蛮大的:
Debug版本:【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_快捷键_05Release版本:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_快捷键_06所以很明显的区别。



三、学会使用快捷键


VS编译器上面的很多功能都是可以使用快捷键来操作的,这样的话可以提高我们的调试速度和能力。【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_07在VS上最常使用的快捷键有以下几个:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_visual studio_08【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_程序错误_09如上图,我们在48行设置断点,当按F5启动调试时会直接跳到这个位置,这里的话大家简单了解一下即可,后面会有很多练习,你懂的哈哈,下面看另外一个快捷键:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_visual studio_10
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_visual studio_11
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_程序错误_12
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_c语言_13
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_visual studio_14这里还要补充一个快捷键:
ctrl+K+f:代码对齐



四、调试时查看当前程序信息

1.查看临时变量的值


启动调试,打开窗口,点击局部变量,如图所示:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_15这里给出下面一段代码的调试:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_16
这时候点开局部变量一栏,系统会自动给出当前程序临时变量的信息,不过这个应用场景还是比较少的。


2.查看监视信息


查看监视很常见,所以这块很重要哦。
使用方法:启动调试,打开窗口,选择监视一栏
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_程序错误_17还是上面一段简单的代码,看看如何使用调试窗口:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_程序错误_18


3.查看内存信息


查看监视信息和查看内存信息在调试中都占有着举足轻重的地位,很常用,所以要好好学习哦。
使用方法:启动调试,打开窗口,选择内存一栏
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_c语言_19
还是下面的一段代码:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_visual studio_20这里的话暂时就不详细分析了,后面会有专门的练习题。


4.查看汇编信息


在调试开始之后,有两种方式转到汇编:
<1>.右击鼠标,选择【转到反汇编】
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_21<2>.调试窗口
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_22


5.查看寄存器信息


有了上面的经验就很简单啦
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_23


6.查看函数调用堆栈


查看函数调用堆栈是用来观察函数调用逻辑的(谁调用谁)
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_24比如下面这段代码:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_visual studio_25所以从标注的信息很明显能看出来,main()调用test(),test()调用test1(),test1()调用test2()



五、多动手去调试,才能有进步


  • 一定要熟练掌握调试技巧;
  • 初学者可能80%的时间在写代码,20%的时间在调试。但是一个程序员可能20%的时间在写代码,80%的时间在调试;
  • 多多使用快捷键,提升效率。所以可想而知调试的重要性


六、经典的调试实例

实例一:1!+2!+…+n!


首先我们知道,如果让我们计算n的阶乘,我们大多会这样写代码:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_26这个代码是没有问题的,所以既然会了求n的阶乘的问题,那么求1!+2!+…+n!的问题就只是在外面套上一层循环的事,这时候我们可能就会写成这样的代码:

//求n的阶乘
#include<stdio.h>
int main()
{
int i = 0;
int j = 0;
int ret = 1;//注意哦,不能是0,用于保存阶乘结果
int sum = 0;//保存最终结果
int n = 0;
scanf("%d", &n);
for (j = 1; j <= n; j++)
{
for (i = 1; i <= j; i++)
{
ret *= i;//计算1~n的阶乘
}
sum += ret;
}
printf("%d\n", sum);
return 0;
}

这个代码看上去挺合情合理的,但是事实上是存在问题的,不信你看:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_快捷键_27事实上我们知道,1!+2!+3!=9,但是这段程序执行结果却是15,所以程序中有bug,好,既然肉眼一下子看不出来,这里只好用调试练手了。
本题很简单,用监视窗口就能找到问题所在:很明显,当j=3时,此时里层循环的ret=2,正确的写法应该是ret被置为1,所以问题出在了这里,将程序错误更改再重新测试。【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_28正确的代码:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_快捷键_29


实例二:nice公司的笔试题


给我们这么一段程序:

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

【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_30题目问:为什么在VS2019上面是死循环打印hehe?
这道题查看内存就能解决啦:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_快捷键_31这是变量i和数组arr的内存区域。不知道你有没有注意到,系统在栈区为变量i申请的空间和为数组申请的空间中间只隔了两个整型,这里刚好符合栈区使用内存的特点:先使用高地址,再使用低地址也有一条数组的特点:随着数组下标的增长,数组的地址由低到高变化。
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_visual studio_32当i=12的时候,再执行arr[i] = 0这条代码,此时地址为0x00EFF894的内存区域放的数变成了0,也就是说i也被置换成了0。这里附加上之前的说明:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_visual studio_33



七、如何写好代码·易于调试的代码

1.优秀的代码


  • 代码运行正常
  • bug很少
  • 效率高
  • 可读性高
  • 可维护性高
  • 注释清晰
  • 文档齐全


常见的coding技巧:


  • 使用assert
  • 尽量使用const
  • 养成良好的编码风格
  • 添加必要的注释
  • 避免编码的陷阱


2.代码示范


要求:模拟实现strcpy()库函数
初级代码:(满分10分 - 得5分)
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_34【敲黑板】:对于字符串拷贝函数,要注意的是是字符串2拷贝给字符串1的,包括字符串2后面的‘\0’ 也会一同拷贝过去,并且要保证 字符串1是足够大的!
优化代码:(满分10分 - 得8分)
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_快捷键_35在写最优代码之前,先看看库函数strcpy原型:
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_36【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_c语言_37函数有返回类型,而且在第二个形参中加入了const 修饰,目的是防止字符串strSource被改变
最优代码:(满分10分 - 得10分)
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_c语言_38


3.const的作用


知识点补充:
const 修饰变量时,变量变成常变量,不能被修改;
同样的,const 也能修饰指针。

const修饰指针的时候(有两种):

  • const放在的左边(const int p) ,修饰的是p,使得p不能改变(保证指针指向的内容不能通过指针修改),但是指针变量p本身可以改变;
  • const放在的右边(int const p),修饰的是p,使得p 不能改变。但是*p可以被修改


题目描述:


下列选项中哪一种形式声明了一个指向char类型变量的指针P,P的值是不可修改的,但P指向的变量的值是可以修改的?
【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_后端_39思路:其实一看到题目中说p的值是不可修改的我们就应该想到const放在*的右边。



七、编程常见的错误

1.编译型错误


直接看错误提示信息,双击会自动跳到错误的代码处,很快就能解决问题,这类错误都是语法问题引起的,比如少写一个分号等情况,属于最简单的一类错误。


2.链接性错误


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


3.运行时错误


借助调试,逐步定位问题所在,属于程序逻辑问题,最难搞的一类错误。


温馨提示:


做一个有心人,积累排错经验。一名优秀的程序员是一名优秀的侦探·每次调试都是尝试破案的过程,加油吧少年们。



遇见安然遇见你,不负代码不负卿。

码字不易,求三连鸭。

【实用调试技巧】掌握了调试技巧,学习数据结构将会事半功倍。_快捷键_40



举报

相关推荐

0 条评论