当前位置: 首页 > news >正文

Visual Studio 的调试(一)

最近事儿很多昂,更新速度相较以往慢了许多,备考六月份的四级,还有学校的期末等等,事儿真的太多啦,所以后面的更新速度也会放慢一点,实在是抽不开身啊诸位,相当抱歉,还望诸君见谅

言归正传,咱们今天来聊一聊有关VS的调试技巧。调试是相当重要的一点,熟练地运用调试可以帮助我们自身检验代码的可行性,并快速地找出问题所在

一 . Bug

不知道大家第一次认识bug是什么时候昂,我第一次听到这个词还是在小学看陈子豪打CF说的,这也算是他的一个口头禅吧,当时我就只知道bug就是一种类似程序意料之外的漏洞的意思

什么是bug呢?其英文的本意是指“ 虫子 ”,“ 昆虫 ”,而在现在的网络中逐渐被演变成了在我们的电脑系统或程序中,隐藏着一些未被发现的问题,也就是“ 缺陷 ”,“ 漏洞 ”的意思

那么这个时候就有小伙伴要问了,这一演变从何而来呢?Good question!查资料可得:

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

历史上的第一个“ bug ”(图源网络) 

 

二 . Debug 和 Release

Debug就是我们常说的调试,顾名思义调试也就是我们找程序漏洞的一个过程,Debug也就是消灭bug的意思。大家调试一个程序,我们首先是要承认出现了问题,然后我们通过一些手段去定位到问题,可以是逐过程的调试,也可以是隔离和屏蔽代码的方式,当我们找到问题的所在,再确定了问题产生的原因,我们就可以去修复代码了

之前我们就有提到过,在VS中,我们可以选择不同的编译环境,如:Debug 和 Release

Debug 称为调试版本 :它 包含调试信息,并且不作任何优化 ,便于程序员调试程序; 程序员在写代码的时候,需要经常性的调试代码,就将这里设置为 debug ,这样编译产生的是debug 版本的可执行程序,其中包含调试信息,是可以直接调试的
Release 称为发布版本 :它往往是 进行了各种优化,使得程序在代码大小和运行速度上都是最优的 ,以便用户很好地使用。当程序员写完代码,测试员再对程序进行测试,直到程序的质量符合交付给用户使用的标准,这个时候就会设置为 release ,编译产生的就是 release 版本  的可执行程序, 这个版本是用户使用的,所以无需包含调试信息等 (如果大家感兴趣的话,可以试着将一个文件分别用 Debug 和 Release保存,我们会发现 Debug版本的所占内存会大一些,这就是因为Debug版本包含了调试信息等

 

三 . VS的调试快捷键

在VS中有着各式各样的快捷键,我这里给大家列举几个常用的、有代表性的:

F10:逐过程,通常用来处理一个过程,一个过程可以是一次函数调用,或者是一条语句
F11:逐语句,就是每次都执行一条语句,但是这个快捷键可以使我们的执行逻辑进入函数内部
在函数调用的地方,想进入函数观察细节,必须使用F11,如果使用F10,直接完成函数调用
F9:创建断点和取消断点
断点的作用 :可以在程序的任意位置设置断点,打上断点就可以使得程序执行到想要的位置暂停执执行,接下来我们就可以使用F10,F11这些快捷键,观察代码的执行细节
条件断点 :满足这个条件,才触发断点
F5:启动调试,经常用来直接跳到下一个断点处,一般是和F9配合使用
CTRL + F5:开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用
(一般我们运行代码都用这个快捷键)
VS更多快捷键了解:http://blog.csdn.net/mrlisky/article/details/72622009

四 . 监视和内存观察

在我们开始调试后,在菜单栏中,调试——>窗口——>监视,我们任意打开一个监视窗口,输入我们想要监视的对象,如:

在监视窗口中观察各项数据:

我们按F10,输入想要监视的对象,然后我们再按一次F10,即可进行到下一条语句,以此类推,直到程序结束跳出

 若是大家觉得我们在监视窗口中观察的还不够细致时,我们可以进入内存中去观察变量在内存中的储存情况,如:

在我们的内存窗口中就可以观察到:

在这里的自动的选项我们可以设置一行显示几列(我们一般会设置为4列):

除此之外,在我们的调试的窗口中还有:自动窗口,局部变量,反汇编、寄存器等窗口,我这里就不一 一为大家赘述, 诸君感兴趣的话可以自行去搜集影视资料学习。

 五 . 有关调试的举例

为了让大家加深对调试概念的理解,咱们在这里用一个经典例题练练手:

大家可以试着想想运行结果是什么?

这个程序运行起来很显然是会死循环的,这一点相信诸君都能看得出来,这题的关键是我们怎么去理解它为什么死循环,用官方的话术解释清楚问题的根本

当我们调试运行到第十个 hehe 的时候还一切正常,但当我们继续的时候,程序可以无休止的打印hehe,大家自己去运行可以发现,最下面的光标是在一直闪烁的,这就证明程序一直在进行,在无休止的打印,像这样:


这个时候就有小伙伴要问了,这也没有报错啊,代码怎么就有问题了呢?

大家要注意,这个代码肯定是错误的,我们数组arr中只能存10个整型,也就是说,当我们 i 变成10的时候,就已经越界访问了,再向后越界访问,我们就有可能覆盖到 i 的地址,从而导致程序的死循环。至于为什么没有报错呢?那是因为程序死循环了嘛,它一直忙着打印 hehe 呢,吃了炫迈一样,根本停不下来,所以来不及报错

此题其内存布局如图:

(1)栈区内存的使用习惯是从高地址向低地址使用的,所以变量i的地址是较大的,及arr数组的地址整体是小于 i 的地址

注意:在VS上切换到X64版本,这个使用的顺序是相反的,在Release版本的程序中,这个使用的顺序也是相反

(2)数组在内存中的存放是:随着下标的增长,地址是由低到高变化

由此可见,在此题中, 随着数组下标的增长,往后越界就有可能覆盖到 i 的地址 ,这样就可能造成死循环

 

这里可能有小伙伴要问了:为什么 i 和 arr 数组之间恰好空出来2个整型的空间呢?这里确实是巧合,在不同的编译器下可能中间的空出的空间大小是不一样的,代码中这些变量内存的分配和地址分配是编译器指定的,所以的不同的编译器之间就有差异了,这也就是为什么题目在一开始就会告诉我们是在Debug 、x86环境下进行

这个理解我们就能够清楚的体会到调试的重要性,只有调试才能观察到程序内部执行的细节,就像医生给病人做B超,CT一样
总结:调试是需要反复去动手练习的,诸君一定要自己动手多调试,从中汲取经验。调试是可以增加程序员对代码的理解和掌控的,掌握了调试的能力,就能看到本质,对程序内部一览无余。熟练的掌握调试技巧是一个优秀的程序员的必备技能

OKK,有关VS中调试的相关知识就给大家聊到这里了。 程序运行时的错误,是千变万化的,这个时候我们可以借助调试,去逐步定位每条语句的问题,调试观察并解决我们程序在运行时出现的问题。当然了,这肯定不是一日之功嘛,而是一个日积月累的过程,无他唯手熟尔。无需多言,诸君记得勤练手,咱们共勉!!!下期再见,886!

相关文章:

  • 42-4 应急响应之文件痕迹排查
  • Rust面试宝典第14题:旋转数组
  • Redis教程(十三):Redis的主从复制模式搭建
  • 【论文阅读】Prompt Fuzzing for Fuzz Driver Generation
  • 设计模式-中介者模式
  • SpringBoot+Mybatis 从头搭建通用管理系统
  • Linux环境下TensorFlow安装教程
  • 简单多状态 dp 问题
  • Facebook广告如何开户以及投放费用?
  • MySQL中创建触发器时,语法与创建存储过程或函数的语法有所不同注意
  • RobotFramework测试框架(1)--官网示例
  • ACM实训冲刺第十九天
  • Vue.js组件设计模式:构建可复用组件库
  • SQL Server2019安装步骤教程(图文)_最新教程
  • Gradient-checkpointing的原理
  • [译]CSS 居中(Center)方法大合集
  • crontab执行失败的多种原因
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • C语言笔记(第一章:C语言编程)
  • Debian下无root权限使用Python访问Oracle
  • docker python 配置
  • HTTP那些事
  • JS笔记四:作用域、变量(函数)提升
  • maya建模与骨骼动画快速实现人工鱼
  • NSTimer学习笔记
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • Vue UI框架库开发介绍
  • vue-loader 源码解析系列之 selector
  • WePY 在小程序性能调优上做出的探究
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 巧用 TypeScript (一)
  • 手机端车牌号码键盘的vue组件
  • 数据科学 第 3 章 11 字符串处理
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • gunicorn工作原理
  • ​香农与信息论三大定律
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #if和#ifdef区别
  • #laravel部署安装报错loadFactoriesFrom是undefined method #
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (1)bark-ml
  • (13):Silverlight 2 数据与通信之WebRequest
  • (2)nginx 安装、启停
  • (2015)JS ES6 必知的十个 特性
  • (55)MOS管专题--->(10)MOS管的封装
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (poj1.2.1)1970(筛选法模拟)
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (十三)Maven插件解析运行机制
  • (四)Linux Shell编程——输入输出重定向
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。