C语言总结十四:实用调试技巧

       在企业开发中,质量和效率显得尤为重要。学会通过debug模式调试代码是每一个开发者的必修课。首先 , 调试是定位软件瑕疵的最直接和最有效的方法 。没有哪个程序员能直接写出没有错误的代码。 而使用以调试器为主的调试工具进行调试是定位瑕疵的最直接方法 , 可以从问题的症状入手 , 正向跟踪或者反向追溯。对于大多数瑕疵 , 使用合适的调试方法可以大大提高定位到问题根源的效率。今天的软件环境在不断向着大型化 、并行化、复杂化方向发展 , 定位瑕疵的难度也在随之不断提高。完全靠读源代码来寻找 bug的方法已经很难适应今天的软件发展形势 。本篇博客详细总结VS2019平台代码调试的方法和技巧,代码的调试同时也是提高编程技能最有效的途径,通过大量的实践调试,可以总结出一定的经验,提高编码能力。

一、什么是Bug?

       bug本意是“昆虫”或“虫子”,现在一般是指在电脑系统或程序中,隐藏着的一些未被发现的缺陷或问题,简称程序漏洞。“Bug”的创始人格蕾丝.赫柏(Grace Murray Hopper) ,她是一位为美国海军工作的电脑专家,1947年9月9日,格蕾丝.赫柏对Harvard Mark II设置好17000个继电器进行编程后,技术人员正在进行整机运行时,它突然停止了工作。于是他们爬上去找原因,发现这台巨大的计算机内部一组继电器的触点之间有一只飞蛾,这显然是由于飞蛾受光和热的吸引,飞到了触点上,然后被高电压击死。所以在报告中,赫柏用胶条贴上飞蛾,并把“bug” 来表示“一个在电脑程序里的错误”,“Bug” 这个说法一直沿用到今天。

C语言总结十四:实用调试技巧_第1张图片

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

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

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

2.1 调试是什么?

       所谓调试(Debug),就是让代码一步一步慢慢执行,跟踪程序的运行过程。比如,可以让程序停在某个地方,查看当前所有变量的值,或者内存中的数据;也可以让程序一次只执行一条或者几条语句,看看程序到底执行了哪些代码。在调试的过程中,我们可以监控程序的每一个细节,包括变量的值、函数的调用过程、内存中数据、线程的调度等,从而发现隐藏的错误或者低效的代码。
        编译器可以发现程序的语法错误,调试可以发现程序的逻辑错误。所谓逻辑错误,是指代码思路或者设计上的缺陷。

       调试是每个程序员必须掌握的技能,没有选择的余地!

2.2 调试器的选择

调试需要借助专业的辅助软件——调试器(Debugger)。现在主流C/C++调试器有下面几种:

1) Remote Debugger

       Remote Debugger 是 VC/VS 自带的调试器,与整个IDE无缝衔接,使用非常方便,初学者建议使用该调试器。

2) WinDbg

       大名鼎鼎的 Windows 下的调试器,它的功能甚至超越了 Remote Debugger,它还有一个命令行版本(cdb.exe),但是这个命令行版本的调试器指令比较复杂,不建议初学者使用。

3) LLDB

       XCode 自带的调试器,Mac OS X 下开发必备调试器。

4) GDB

        Linux 下使用最多的一款调试器,也有 Windows 的移植版,如果你不使用 VC/VS,GDB 将是一个不错的选择。

2.3 调试的基本步骤

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

2.4 debug和Release的介绍

       在VS上编写代码时,就能看到如下有Debug和Release两个选项,分别是什么意思呢?

C语言总结十四:实用调试技巧_第2张图片

⭐Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序;
程序员在写代码的时候,需要经常性的调试代码,就将这里设置为debug,这样编译产生的是debug版本的可执行程序,其中包含调试信息,是可以直接调试的。
⭐Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。当程序员写完代码,测试再对程序进行测试,直到程序的质量符合交付给用户使用的标准,这个时候就会设置为release,编译产生的就是release版本的可执行程序,这个版本是用户使用的,无需包含调试信息等。

C语言总结十四:实用调试技巧_第3张图片

       对比可以看到从同-段代码,编译生成的可执行文件的大小,release版本明显要小,而debug版本明显大。因为debug版本包含调试信息 。

三、Windows环境调试介绍(重点掌握)

3.1 调试环境准备

首先是环境的准备,需要一个支持调试的开发环境,应该把VS上设置为Debug,如图:

C语言总结十四:实用调试技巧_第4张图片

3.2 VS调试快捷键的使用

调试最常使用的几个快捷键:
1、F9:创建断点和取消断点:

        断点的作用是可以在程序的任意位置设置断点,打上断点就可以使得程序执行到想要的位置暂定执行,接下来我们就可以使用F10,F11这些快捷键,观察代码的执行细节。

2、F5:启动调试:

      经常用来直接跳到下一个断点处,一般是和F9搭配使用。
3、F10:逐过程调试:

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

      就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部。在函
数调用的地方,想进入函数观察细节,必须使用F11,如果使用F10,直接完成函数调用。
5、CTRL+ F5:开始执行不调试:

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

 

C语言总结十四:实用调试技巧_第5张图片

C语言总结十四:实用调试技巧_第6张图片

3.3 普通断点

      默认情况下,程序不会进入调试模式,代码会瞬间从开头执行到末尾。要想观察程序的内部细节,就得让程序在某个地方停下来,我们可以在这个地方设置断点。
     所谓断点(BreakPoint),可以理解为障碍物,人遇到障碍物不能行走,程序遇到断点就暂停执行。严格来说,调试器遇到断点时会把程序暂时挂起,让程序进入一种特殊的状态——中断状态,这种状态下操作系统不会终止程序的执行,也不会清除与程序相关的元素,比如变量、函数等,它们在内存中的位置不会发生变化。关键是,处于中断状态下的程序允许用户查看和修改它的运行状态,比如查看和修改变量的值、查看和修改内存中的数据、查看函数调用关系等,这就是调试的奥秘。

在debug模式下,下断点即可进行调试,那么如何进行调试呢?

第一种:光标定位在调试行,按下快捷键F9即可下断点,在按F9即可取消断点。

第二种:调试的代码行位置行号前的灰色区域左键点击出现红色的实现圆圈,便是断点。

第三种:鼠标右击,出现菜单栏点击:断点-插入断点。

C语言总结十四:实用调试技巧_第7张图片

C语言总结十四:实用调试技巧_第8张图片

断点快捷键

  1. F9-插入断点
  2. Ctrl+F9- 禁用断点
  3. Ctrl+Shift+F9-删除所有断点 

3.4 单步调试

C语言总结十四:实用调试技巧_第9张图片

1、 第一步:先下断点,再工具栏选择调试(或者直接使用快捷键F5),后点击开始调试。

C语言总结十四:实用调试技巧_第10张图片

2、第二步:程序运行到断点位置阻塞,根据不同的场合选择不同的按键,开始我们的调试

C语言总结十四:实用调试技巧_第11张图片

3、第三步:实时查看变量信息

     使用【自动窗口】变量信息可能展示不完全。 当数组作为参数时,形参只能看到数组名,不能看到数据本身,需要添加【监视】窗口查看更详细内容信息。

3.1 打开监视窗口查看变量

      开始调试后,在菜单栏中[调试] -> [窗口] -> [监视],打开任意一个监视窗口,输入想要观察的对象就行。

C语言总结十四:实用调试技巧_第12张图片

C语言总结十四:实用调试技巧_第13张图片

3.2 打开内存窗口查看变量的存储的值和地址

C语言总结十四:实用调试技巧_第14张图片

C语言总结十四:实用调试技巧_第15张图片

在打开内存窗口后,要在地址栏输入: arr, &num, &C,这类地址,就能观察到该地址处的数据。

3.3 查看汇编信息

  1. 第一种:鼠标右击,转到反汇编即可 
  2. 第二种:利用反汇编窗口

 C语言总结十四:实用调试技巧_第16张图片

C语言总结十四:实用调试技巧_第17张图片 

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

  1. 一定要熟练掌握调试技巧。
  2. 初学者可能80%的时间在写代码,20%的时间在调试。但是一个程序员可能20%的时间在写程序,但是80%的时间在调试。
  3. 我们所讲的都是一些简单的调试。
  4. 以后可能会出现很复杂调试场景:多线程程序的调试等。
  5. 多多使用快捷键,提升效率。

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

6.1 优秀的代码

1. 代码运行正常

2. bug很少

3. 效率高

4. 可读性高

5. 可维护性高

6. 注释清晰

7. 文档齐全

常见的coding技巧:

1. 使用assert

2. 尽量使用const

3. 养成良好的编码风格

4. 添加必要的注释

5. 避免编码的陷阱。

七、编程常见的错误

7.1 编译型错误

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

7.2 链接型错误

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

7.3 运行时错误

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

八、经验分享

接下来我们为大家总结了一些调试的经验以及调试思路:
       当我们运行我们编写的程序发现运行结果与我们预想的不同的时候,我们可以先用即时窗口,使用一些比较简单的数据来测试我们的各个函数运行结果是否符合我们的预期,如果都符合的话,我们可以使用程序中产生的一些比较复杂的数据来进一步测试我们的各个函数,直至找到可能导致错误的函数。
      找到可能导致错误的函数之后,我们就可以使用逐语句调试来一步步跟踪运行程序了,渐渐的的我们就可以缩小范围直至定位错误(无关代码可以考虑暂时注释掉),在这期间,我们要仔细观察程序运行过程中各个数据的变化情况,观察的仔细与否直接与我们能否找到错误直接挂钩。
       如果上一步运行的数据一直是正常的,我们就可以排除这个函数的嫌疑了(减少对他的调试次数)。此时,我们就应该考虑问题是否出现在之前的函数上了,可能因为偶然性,我们第一次测试函数的时候并没有发现其错误,导致范围锁定产生偏差,此时我们需要再次耐心的对所有未排除嫌疑的进行调试,直至再次找到出错的函数。再重复上一步,直至找到错误。

       可以看到,调试其实是一项比较复杂的活,需要大量的操作,所以在我们编写代码的时候要万分谨慎!因为很多时候,BUG都是因为我们的粗心大意导致的笔误引起的!

       以上便是我为大家带来的VS调试实用技巧内容,若有不足,望各位大佬在评论区指出,谢谢大家!可以留下你们点赞、收藏和关注,这是对我极大的鼓励,我也会更加努力创作更优质的作品。再次感谢大家! 

你可能感兴趣的:(C语言系统精讲,c语言,开发语言)