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

C语言【调试】(个人笔记版)

调试

  • 前言
  • 一、Bug
  • 二、调试工具
    • 1.DeBug
    • 2.Release
  • 三、调试快捷键
    • 1、断点
  • 四、调试时查看程序的当前信息
    • 1、查看临时变量
    • 2、查看内存
    • 3、查看调用堆栈、汇编、寄存器
  • 总结


前言

这篇文章大都是我的个人笔记: 调试在日常程序设计中是很重要的。调试说白了就是为了解决代码的bug问题。但是如何学好调试,成为一名会解决问题的学习者呢?这篇文章我们就来探讨一下调试问题。


一、Bug

平常我们写完代码运行的时候,总会遇到一些出乎你意料的错误。比如,很经典的:

我写完代码啦->运行一下->为什么错误了呢?-这里改改,再运行一下->为什么又错误了呢?->再改改,再运行->这下可以了,但是为什么呢?

以上是不是你的真实写照呢?其实,这种调试的方法叫做迷信式调试,是一种不可取的调试方法,原因也很简单,因为你不知道代码具体哪里有问题,只能靠猜,而且大多数时候,你都不知道改完后正确的代码为什么是这样的。

二、调试工具

1.DeBug

Debug是被称为程序员版本,里面不做任何优化,可以方便程序员检查代码。
(按一下f10就会走一步,并且是一步一步来的)

2.Release

Release版本被称为发布版本,里面进行了各种优化。
(调试的时候就是一步到位)

三、调试快捷键

  1. F5 — — 启动调试,常用来直接跳到下一个断点处。常以F9配合使用
  2. F9 — —创建断点和取消断点。(后面我会说明断点点作用)
  3. F10 — —逐过程。通常用来处理一个过程。一个过程可以是一个函数调用,也可以是一条语句。(一步一步走)
  4. F11 — —逐语句。每次都执行一个语句,在遇到函数时会进入函数内部。(相对F10会更加细致)
  5. CTRL F5 — —执行但是不调试,也就是不经历调试而直接执行代码

以上就是常用的快捷键了

1、断点

断点大致意思就是让程序在指定的位置停下。
举个例子

int i = 0int arr[10] = {0};
for(i = 0; i < 10; i++){arr[i] = i;
}
for(i = 0; i < 10; i++){printf(%d”, arr[i]);
}

这里,我们在第二个for循环的地方按一下F9,就会产生一个断点。
正常情况下如果你调试,那么程序就会先进入到第一个循环,然后你按一下键盘他就执行一次。不过你知道第一个循环里的内容是没有问题的,你想去第二个循环的地方进行调试。但是程序要到第二个循环的话就需要先把第一个循环跑完,这就会很繁琐。
有了断点后,程序就会一次跑完断点之前所有的代码,在断点处停下,这样一来,你就可以继续进行你的调试了。

如果还没理解为什么这样的话,我就再举个例子:
现在假设你有5000行代码,你完全不知道代码哪里出了问题,你就得一次一次一行一行一直慢慢调试下去。这样下来,手都要先按断掉了。有了断点,你就可以在你所知道的没有问题的代码前设置断点,跳过这些代码。大大提高你的效率。

不过要注意的是,当出现两个断点时,并不是按一下F5就会跳到下一个断点处。按F5时,他会跳到一个**“逻辑断点”。**

意思是,如果断点假设在第一个循环中,并且我第二个循环的开始(不在循环体内)也设置了一个断点。那么第一次F5是进到第一个断点没错,但是我再按一次F5就不是跳到第二个断点了,而是在第一个循环中在来一次。

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

1、查看临时变量

int a = 0;
int b = 100;
int c = 200;
printf(%d”, a);

如果你想看这些临时变量的值时,该怎么办呢?
在这里插入图片描述
注意:一定是在启动调试(F10)的时候才能打开
流程:窗口 -> 自动窗口
或:窗口 -> 局部变量
或:窗口 -> 监视 (常用)

在这里插入图片描述
这里:
名称这一栏是可以进行输入的,只要输入的合法就可以。
值会显示当前名称的状态
类型顾名思义就是变量的类型了

这里我来说明一下数组在传参时应该怎么查看数组里的内容
在这里插入图片描述

我想查看数组arr的成员,那么我只需要在监视窗口内的值这一栏输入arr,4就可以看到前四个值了。
解释一下,因为指针传递的是数组的首元素的地址,所以我输入arr就是查看arr数组的第一个值,同理,我想看四个我就输入arr,4 我想看10个我就输入arr,10。

2、查看内存

创建一个数组并赋予初值,我们可以查看该数组在内存中存放的位置

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

在这里插入图片描述

内存窗口比较复杂
首先,我们要把需要看的东西写在地址栏上。
然后这里会有三列,第一列表示地址,第二列表述数据,第三列表示编译器推测的数据信息。
先来看看第一行第二列的数据:
01 00 00 00
再来看看第一列的数据:
0x00 8F FB C8
这俩有什么关联呢?
01 是内存中存储的数据,对应的就是第一列C8的位置,这第一列表示地址,而又因为我们只显示4列。所以01 00 00 00这个数据对应的地址00 8F FB C8+4就是00 8F FB CC。而我们第二行第一列的数据00 8F FB CC末尾处正是CC。所以答案显而易见了,这就是一个连续的地址,数据是存储在连续的内存空间中的
画个图会更好理解:
在这里插入图片描述

1.栈区内存的使用习惯是先使用高地址处的空间,再使用低地址处的空间
2.而数组下标的增长地址是由低到高变化的。
所以这里,我们的数据 1 的地址往上+4个字节就是数据 2 的地址,再往上就以此类推。
当然这里还可以补充堆与栈的知识。但是这部分知识与调试无关,我会在下次的文章中详细讲解一下堆栈。

3、查看调用堆栈、汇编、寄存器

这部分用的较少,但是调试窗口是可以查看的
在这里插入图片描述

总结

这篇文章全然是我自己的笔记,但是也可以方便大家快速理解一些调试中的术语的解释。好啦,这篇文章先到这里,如果有补充我会重新编辑,那么,下篇文章见!

http://www.lryc.cn/news/465485.html

相关文章:

  • 连锁收银系统
  • 5.2024.10.21
  • 前端Socket互动小游戏开发体验分享
  • react项目,通过自定义 separator 属性来修改日期选择器中间的分隔符:
  • 双十一有啥好用的家居好物推荐?2024性价比高的超声波清洗机推荐
  • 比亚迪车机安装第三方应用教程
  • 移动零---双指针法
  • MoeCTF 2024 ---Misc方向WP
  • 【我的 RT 学习手札】信息收集
  • CMake变量:CMAKE_FIND_LIBRARY_SUFFIXES
  • 在使用 RabbitMQ 作为消息代理时,多个 Celery 实例(或应用)可以共享同一个 RabbitMQ 实例
  • ARM在嵌入式开发中的作用有哪些?
  • -webkit-box-orient属性丢失?
  • openKylin系统SSH服务配置结合cpolar轻松实现开放麒麟远程连接
  • 我的世界之合成
  • java基于SpringBoot+Vue+uniapp微信小程序的自助点餐系统的详细设计和实现(源码+lw+部署文档+讲解等)
  • AI 编译器学习笔记之八 -- Python基础学习
  • 盘点近几年腾讯的精选面试题(c/c++研发岗)
  • C++详细笔记(四)
  • 架构师备考-背诵精华(系统架构评估)
  • QT 实现自定义水波进度条
  • 厨房老鼠数据集:掀起餐饮卫生监测的科技浪潮
  • Linux系统:more命令
  • ESP32-S3学习笔记:分区表(Partition Table)的二进制分析
  • 04,perl
  • Js 更加优雅地实现Form表单重置
  • 基于微信小程序的驾校预约系统设计与实现
  • 利用python进行数据处理,得到对自己有利的内容
  • Java面试题五
  • 2013 lost connection to MySQL server during query