【C语言】代码的调试技巧-程序员宅基地

技术标签: c语言  开发语言  

Hello everbody!时隔一周的时间,咱们又见面喽!最近一直在忙操作系统的事情,没能抽出时间,还请见谅呀。

今天,我打算给大家讲讲有关调试的知识。有些宝子是非科班,可能对调试还是挺陌生的。等c语言学习过后到了数据结构,咱们需要编写的程序的代码量明显增加。单是初阶数据结构的顺序表,链表,代码量就轻轻松松超过一百行。如果我们写出了BUG,迟迟找不到出现问题的原因,这将是一件令人十分抓狂的事情。有些时候,咱们碰碰运气,这儿改改,那儿改改。咦!程序居然该对了!这时我们可能十分开心,觉得之前努力敲的代码总算没有白费,可是回头一想:刚才的程序到底错在哪里呢?

到了数据结构部分,如果不会调试,可以说是寸步难行。因此,我认为给大家讲一讲调试是十分有必要的,这可以大大提升我们的学习效率。

1.学习工具

建议大家使用Visual Studio进行学习。因为它的调试功能是比较强大的,而且它与标准C的契合度比较高。不太建议使用dev和vc6.0。dev的调试功能不太行,与标准C的契合度不如Visual Studio,长期使用会给大家带偏的,而且它没有中文版本,给我们的学习带来了比较大的阻碍。vc6.0的版本比较老了,而且已经很久没有更新了,也不太建议使用。

下面我将用Visual Studio2022版给大家讲讲调试技巧。

2.小问题考考大家

咱们先看一看这个小程序,但凡有学过C语言的宝子们都可以看出来这个程序的问题:就是越界了呗!arr数组明明只有十个数据,你却循环了13次,这肯定是脑子进水了的写法!咱们把for循环中的13改成10,那程序肯定就正常啦!是的,你说的都对!但是我想问的是:这个程序为什么是死循环呢?如果你去公司应聘,面试官给你一个类似的程序,问你该程序可能输出的结果,你能答上来嘛?当然,如果知道原因的小伙伴可以把答案写在评论区呦!

想要知道原因,咱们就必须调试!逐字逐句的分析代码的运行情况!

到本文结尾,我会给大家讲讲死循环的原因!

3.Debug和Release的介绍

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

Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以使用户很好的使用。换句话说,公司研发的成品,用户拿到的就是发布版本。

看,还是同样的代码,换成Release版本就不再是死循环了。可见Release对先前的版本确实进行了优化。

当然,我们同样可以通过对比Debug版本的可执行程序和Release版本的可执行程序的大小也可以看出,Release版本的可执行程序要小得多。

4.学会快捷键

1.CTRL+F5,这个大家应该是最熟悉的。作用就是让我们写好的程序跑起来。

2.F9,创建断点和取消断点。断点的作用:可以在程序的任意位置设置断点。这样就可以使得程序在想要的位置随意停止执行,继而一步一步执行下去。当然也可以手动设置断点。

如图,在代码的最左边边用鼠标点一下即可。当然,我们也可以设置调试断点:

3.F5,启动调试,经常用来直接跳到下一个断点处。很显然,这个快捷键是要和断点联合使用的!

4.F10,逐过程,一个过程可以是一个函数调用,也可以是一条语句。

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

5.调试找出死循环的原因

下面我将用上文死循环的例子用调试功能检查一下死循环的原因!

首先我们需要主观判断一下程序出错的大致位置,由于这是一个死循环程序,那么大概率是循环体出错了。所以我们把断点的位置设置在循环体处。(左边的小红点就是断点)

断点设置好后再使用快捷键F5开始调试。

开始调试后我们可以看到程序执行到第14行就自动停了下来,前面的test函数已经执行过了,hehe已经打印到屏幕上。如果宝子们觉得这样观察得还不够细致,也可以这样:

点击调试按钮,找到窗口,窗口里面有一个监视选项,监视中的四个选项都是一样的,随便点击一个即可。

这是打开监视后的界面,我们可以输入任何我们想观察的变量。这个程序是死循环,那就表明i总是小于13的,我们就可以观察一下i的变化。当然,如果你想看得更加清楚,arr数组也可以观察一下!

输入i和arr后,我们可以十分清晰的观察到目前i的值为1,arr数组中首元素已被赋值为1。

这时我们可以用F10或是F11让程序一步一步执行下去,并密切关注i和arr数组的变化情况:

目前开始执行第三次循环,目前一切正常,没有出现什么问题,那么我们就可以继续调试下去,直到出现问题为止。

i的值已经来到了9,说明循环已经跑了十次,目前程序仍然是正常的。说明问题出在数组越界的部分,但是到后面arr数组就观察不到了怎么办呢?

其实调试功能是非常强大的,我们依然可以观察arr[10],arr[11],arr[12]。只需输入到监视窗口中即可!

我们把arr[10],arr[11],arr[12]输入到监视窗口后,由于循环只跑了十次,arr[10],arr[11]还没有被赋值,编译器给到的是随机值。但是arr[12]好像格外的与众不同,它的值是9,i的值也是9!这难道是巧和嘛?目前还不能十分确定具体的原因,那么我们继续按F11让程序走起来。

我们进入第11次循环的内部,此时arr[11]的值被该成了1(看来这个程序的胆子还是很大的,都越界了还可以改)。但这并不是我们观察的焦点,我们更应该把注意力放在i和arr[12]的变化情况。

我们可以看到:进入第11次循环后,由于自增,i的值变成了10。但是神奇的是arr[12]的值也变成了10!这就不正常了,按理说arr[12]的值不该变呀,还没轮到它变呢!

这时,相信聪明的宝子们已经发现该程序死循环的原因啦!当然为了观察得更清楚,我们依然可以继续调试下去。

调试到这里,i得值增加到了12,arr[12]也变成了12,那么下一步,就要对arr[12]赋值啦,当arr[12]的值变成一后,i会怎么变呢?是也变成1,还是不变呢?

arr[12]赋值为1后,i不出意外的也变成了1。那么死循环的原因就呼之欲出啦!i的值最大就是12,永远不会超过12,这就是死循环的原因。但是为什么i的值和arr[12]的值一致,并且时时刻刻跟随着它变化呢?

难道它们两个是同一块空间嘛?如果是同一块空间的话,这一切就解释的通了。当然,这也只是我们的猜测。我们同样可以通过调试来验证我们的猜想!

通过观察它们的地址,我们发现,它们的地址居然是一样的!既然地址一样,那么它们就是同一块空间,它们的值同时变化也就不奇怪了!

6.死循环的底层逻辑

我们已经用调试功能找出了死循环的原因,那么为什么arr[12]的空间刚好和i的空间一致呢?真的那么巧合嘛?

其实这取决于局部变量空间的创建逻辑。

像i,arr都属于局部变量。局部变量都创建在栈区,而栈区内存的使用习惯是:从高地址向低地址使用。而数组随着下标的增长,地址是由低到高变化的。

再次仔细观察我们的代码会发现:i是先声明的,而arr是后声明的,那么i的地址就必然比arr的地址高,至于高多少就取决于编译器了,像刚才我们用的vs2022,i的地址就刚好比arr地址高了3个整型空间。当然如果是vs2019可能只高两个整型空间。

大家也可以验证一下自己的编译器是什么情况!

那换句话说,如果我们先声明arr,再声明i。那么arr的地址就必定比i高。不管数组再怎么越界与i也没有任何关系,就不会出现死循环啦!

7.结语

当然,仅仅学会这些快捷键是远远不够的。一个人的调试水平不是一蹴而就,而是日积月累,调试能力逐渐提高的。今后在公司面试时,你的调试能力也是面试官重点关注的呦!因此在面试时,咱们写出了错误的代码不要紧张,一个程序员写出BUG再正常不过啦!运用咱们深厚的调试功底,在短时间内找出BUG并改正同样可以让面试官眼前一亮。所以,加油吧各位宝子们!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/c565114/article/details/134234817

智能推荐

网络安全入门 5 天速成教程_ WEB 安全渗透攻防技术-程序员宅基地

文章浏览阅读812次,点赞8次,收藏30次。希望能帮助大家尽快入门。

Mtk Camera Hal到驱动的流程(一)_mtk imageio-程序员宅基地

文章浏览阅读4.3k次,点赞7次,收藏78次。(1)架构介绍(A)Camera的框架分为Kernel部分和Hal部分Kernel部分:image sensor driver——负责具体型号的sensor的id检测,上电,以及在preview、capture、初始化、3A等等功能设定时的寄存器配置;ISP driver——通过DMA将sensor数据流上传;Hal部分:imageio——主要负责数据buffer上传的pipe;drv——包含imgsensor和isp的hal层控制;feature io——包含各种3A等性能配置;_mtk imageio

相机成像原理以及旋转_摄像机平移旋转的原理-程序员宅基地

摘要:相机成像原理涉及点在不同坐标系中的矩阵变换,包括世界、相机、像平面和像素平面坐标系。具体变换关系可用矩阵表达,可求得单位向量。

Android 13中的 Open Mobile API_sim trasmit apdu-程序员宅基地

文章浏览阅读4.4k次,点赞4次,收藏12次。SE 也就是 Secure Element,译为 “安全元素”主要应用场景在 手机手表交通卡、门禁、虚拟钱包、虚拟SIM卡,以及其他身份认证的且对安全级别有一定要求的业务。_sim trasmit apdu

【Flutter混编】InAppWebView常见配置&相册问题处理-程序员宅基地

文章浏览阅读5.1k次。Flutter自带WebView不想说啥了,就这样吧。反正一番周折之后选择使用第三方的InAppWebView。看源码可以看出本质上是用了Platform调回原生平台的webview,但是xing nen_inappwebview

springboot ControllerAdvice 类似上传超出文件大小异常无法捕获问题详解及解决方式_handlemaxuploadsizeexceededexception-程序员宅基地

文章浏览阅读6.7k次,点赞2次,收藏10次。spring boot/mvc通过@RestControllerAdvice或者@ControllerAdvice配合@ExceptionHandler实现全局异常统一处理在spring web项目开发中,我们经常会遇到各种exception,这些exception根据业务或者场景不同抛出不同的信息和返回类型,有的exception需要返回json数据格式的错误,有的exceptio..._handlemaxuploadsizeexceededexception

随便推点

如何使用mp4v2将H264+AAC裸流录制成mp4文件,并保持音视频同步【源码】【mp4】【录像】_mp4v2 同步音视频-程序员宅基地

文章浏览阅读6.5k次,点赞2次,收藏23次。前言: mp4文件目前已经成为了流媒体音视频行业的通用标准文件格式,它是基于mov格式基础上演变来的,特别适合多平台播放,录制一次,多个平台都可使用。但是,由于mp4格式相对比较复杂,直到mp4v2这个开源工程的出现,解决了这个问题。 通常,我们在使用mp4文件时,会遇到两个问题:如何从已有的mp4文件中抽取音视频数据帧;如何将音视频数据帧录制成mp4文件,并保持音视频同步。 上..._mp4v2 同步音视频

基于SpriteKit的游戏,如何添加界面-程序员宅基地

文章浏览阅读615次。使用UIKit开发界面众所周知,SpriteKit并不提供各种UI常见的组件,连基本的Button都没有,唯一有的文本显示组件Label还不支持多行。那么到底该用什么来为基于SpriteKit的游戏开发界面呢?可以肯定的回答:用UIKit。大家都这么想了,可是具体该怎么做,却不是很清楚。 如何把UIKit界面元素嵌入场景界面遇到的第一个问题是,如何把UIKit组件加入到场景中。UI

Scrapy实战:爬取知乎用户信息_运用分布式框架抓取知乎网站用户的信息,包括用户的姓名(昵称)、一句话介绍、部分-程序员宅基地

文章浏览阅读1.5k次,点赞2次,收藏8次。思路:从一个用户(本例为“张佳玮”)出发,来爬取其粉丝,进而爬取其粉丝的粉丝…先来观察网页结构:审查元素:可以看到用户“关注的人”等信息在网页中用json格式保存在data中。当把鼠标移到列表中的某个名字上时,可以看到浏览器产生了一个Ajax请求:请求的url后面加上了很长的一串查询字符串。并且json中也请求了许多详细的信息。这与该用户的主页基本是对应的:实战我们..._运用分布式框架抓取知乎网站用户的信息,包括用户的姓名(昵称)、一句话介绍、部分

23种设计模式——装饰者模式-程序员宅基地

文章浏览阅读3.9k次,点赞8次,收藏35次。文章目录23种设计模式——装饰者模式1、装饰者模式概述2、装饰者模式的结构3、装饰者模式的实现4、装饰者模式的应用场景23种设计模式——装饰者模式1、装饰者模式概述背景有些人为了早上多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框、咖啡加调料等,都是装饰器模式。装饰者模式的定义装饰者(Decorator)模式的定义:指在不改_装饰者模式

html css的参考文献,网页制作论文参考文献大全 网页制作参考文献有哪些-程序员宅基地

文章浏览阅读6.2k次。【100个】关于网页制作论文参考文献大全汇总,作为大学生的毕业生应该明白了网页制作参考文献有哪些,收集好参考文献后的网页制作论文写作起来会更轻松!一、网页制作论文参考文献范文[1]开展电脑社团活动培养学生信息素养——中学生网页制作社团活动报告.童宇阳,2009第九届中国教育信息化创新与发展论坛[2]项目教学法在《网页制作基础》课程中的应用.胡永刚,20072007无锡职教教师论坛[3]基于SVG的..._计算机网页制作相关参考文献

生信学习过程中遇到的问题_couldn't build a bowtie2.index from hg38.fa-程序员宅基地

文章浏览阅读1.7k次。前言:记录在自学生信过程中所遇到的一些问题,如何去解决的。希望我的经验可以对他人有帮助。 注意:不要复制代码,因软件版本更新等问题,命令会变化的。重点学习怎么去解决问题。 一:执行zcat cz2_1.fq.gz,屏幕出现了群魔乱舞,想要恢复到正常的命令行模式下。 1、直接终止正在运行的程序,使用ctrl+c。 2、让程序进入后台运行,使用ctrl+z,进..._couldn't build a bowtie2.index from hg38.fa

推荐文章

热门文章

相关标签