C生万物 | 程序员必备实用调试技巧分享-1

简介: C生万物 | 程序员必备实用调试技巧分享

一、前言

本文,我们就来讲讲如何去进行调试,对于一名优秀的程序员来说,除了要熟练写业务逻辑外,还要学会如何去调试代码,这是至关重要的!

🔰 那我们该如何去调试哪些东西呢?使用什么去调试呢?如何调试呢? —— 让我们带着上面这些问题一起进入调试的学习:book:

二、什么是Bug?

首先来讲讲我们要调试的是哪些东西,调试又称作【DeBug】,那这个Bug又是什么?

==“1949 年 9 月 9 日,我们晚上调试机器的时候,开着的窗户没有纱窗,机器闪烁的亮光几乎吸引来了世界上所有的虫子。果然机器故障了,我们发现了一只被继电器拍死的飞蛾,翅膀大约 4 英寸。”==

  • 上面是计算机编程的先驱 —— 【格蕾丝·霍普】在一次的机器调试中所遇到的现象,它也是发现Bug的第一人
  • 这导致计算机错误的飞蛾,也是第一个计算机程序错误

image.png 注:参考资料

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

1、导学引入

调试(英语:Debugging / Debug),又称除错,是发现和减少计算机程序或电子仪器设备中程序错误的一个过程。

所有发生的事情都一定有迹可循,如果问心无愧,就不需要掩盖也就没有迹象了,如果问心有愧,就必然需要掩盖,那就一定会有迹象,迹象越多就越容易顺藤而上,这就是推理的途径:mag:

  • 还记得当年我的老师曾经和我讲 “一名优秀的程序员是一名出色的侦探”,我觉得说得很正确,在日常中我们总会写很多的代码,但是呢不一定每个逻辑都能写对,这个时候就需要我们去进行调试了,==每一次调试都是尝试破案的过程==

顺着这条途径顺流而下就是犯罪( ‵▽′)ψ,逆流而上,就是真相🕵️‍

可是在日常的工作中很多人又是怎么写代码的呢?

下面还有《神秘的程序员们》这部漫画里的一组图片,让我们看到了一个【迷信式调试】的程序员,我们应该杜绝这种行为!

image.png

2、调试的基本步骤

好,接下去就让我们正式地来学习调试吧:computer:

首先我们要了解的是调试的基本步骤

  1. 发现程序错误的存在
  2. 以隔离、消除等方式对错误进行定位
  3. 确定错误产生的原因
  4. 提出纠正错误的解决办法
  5. 对程序错误予以改正,重新测试
  • 我们都说【万事开头难】,想要去通过调试解决一个问题,那就需要先找到这个问题,怎么找呢?谁去找呢?这里一共会有三种人:

首先第一个的话就是程序猿本猿🐒 我们会尽量地做到让自己的代码不出问题,减少Bug

image.png

第二个的话就是软件测试人员:man: 它们的任务就是尽量多得找出程序中的Bug,保证产品在上线的时候不会出现问题

image.png

那最后一个就是在使用软件的客户🤵,因为软件做出了来就是为了给客户用的,我们会根据客户的反应来不断完善所研发出来的产品image.png那么在找出了问题之后,接下去我们要做的就是去做一系列的排查了,这也是我们本文所要学习的内容

3、Debug和Release的介绍

接下去呢,我们再来说说有关【Debug】和【Release】的区别

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

🔰 Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用

  • 接下去我们就到VS中来观察一下

Debug版本

image.pngRelease版本

image.png

  • 当我们在不同的版本下去执行程序的时候,当前工程目录下就会生成对应的文件夹

image.png

  • 而且对于不同的版本来说,它们所形成的可执行程序大小也各不相同,可以看到优化后的Release版本体积小了很多

image.png

int main()
{
  char* p = "hello bit.";
  printf("%s\n", p);
  return 0;
}
  • 我们还可以通过汇编来进行观察,便可以发现相较于Debug版本而言,Release在底层做了许多的优化工作

image.png

四、Windows环境下VS调试介绍

好,清楚了调试的基本技巧之后,我们正式地来介绍一下在Windows中的VS下该如何去进行调试

1、调试环境的准备

  • 我们在准备进行调试的时候,一定要让自己处于Debug模式下,如果是其他模式的话是无法进行调试的

image.png

2、学会快捷键

  • 在调试这一块,我们一般会去使用一些快捷键来进行操作,这样在调试的过程中就可以专注于代码本身,而不是去关注进入下一步要点击哪个按键,下图中我框出来的几个就是比较常用的

image.pngF5

启动调试,经常用来直接跳到下一个断点处。

F9

创建断点和取消断点。熟知这个快捷键,我们便可以在程序的任意位置设置断点,由调试者本身来进行操控,做到得心应手。

F10

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

F11

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

Ctrl + F5

开始执行不调试,如果你想让程序直接运行起来而不调试就可以直接使用。

👉想知道更多快捷键?点我👈

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

清楚该如何去进行一步步地调试之后,如果我们在调试的过程中想要查看一些当前程序的相关信息呢?该如何去进行查看

  • 立马到VS中来看一下,在点击【调试】⇒ 【窗口】里面有很多的内容可供我们去进行查看,不过呢这些窗口都是需要再调试起来之后才可以的

image.png

  • 我们可以看一下,如果没有调试起来点击【窗口】出现的就只会是一些简答的窗口,有些窗口我们就看不到了,所以一定要调试起来!!!

image.png💬 接下去呢,就让我们去学习一下这些相关的窗口该如何使用:book:

3.1 查看临时变量的值

  • 首先的话就是去看看我们在调试过程中所需要查看的临时变量的值,在这之前呢我们要先开启【窗口】中的【监视】,随便点开哪一个都是一样的

image.png

  • 接下去,开始调试起来,我们就可以在【监视】窗口中敲入当前程序的变量名然后去观察它们在调试过程中所发生的变化,不仅可以增加也可以删除,读者可以自行去试试,这里不做演示了

image.png

  • 然后我们调试起来,观察右侧的值发生了怎样的变化🎇

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/000a0ae345304eff865183f69c65f639~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp#?w=1153&h=448&e=gif&f=120&b=cee8d2

当然,除了【监视】窗口可以看这些内容之外,我们还可以通过【自动窗口】【局部变量】这些来进行查看

image.png

  • 可以看到,我们在使用【自动窗口】进行调试的时候,发现里面的变量会随着程序的执行而发生变化,却不会是一直固定的几个值,无法进行自行输入和删除,所以我们若是像看一些变量的时候就不到了

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/22d400a35d1049b3a5c4feee39f7d380~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp#?w=1469&h=566&e=gif&f=90&b=cfe9d6

  • 再来看看【局部变量】又是怎样的

image.png

  • 如果有看过 函数栈帧 的同学应该就可以知道局部变量在出了作用域之后就销毁了,所以当我们在进行调试的时候窗口中只会显示当前函数栈帧中的变量,出了当前函数的作用域之后就销毁了

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7258187885ef44689d740e08d59c494c~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp#?w=1468&h=602&e=gif&f=106&b=cee7d4

综上所述,我们在进行调试的时候还是尽量选择【监视】窗口来进行观察,因为在里面我们可以任意地增、删变量,任何东西都可以由调试者来进行控制,而不是由VS来进行控制

3.2 查看内存信息

  • 接下去我们再来看下一个功能 ⇒ 【内存】

image.png

  • 首先你要知道的是如何精准地找到某个变量的地址,也就是在上面这个框中输入【& + 变量名】即可

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/01d7c0ed974d40b9899ec1de98966abf~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp#?w=1468&h=602&e=gif&f=84&b=cfe9d8

  • 接下去我们就可以去看看当前的变量在内存中到底是怎么存放的,例如这个变量a在内存中左侧即为其地址,中间就是他的值,0a即为10的十六进制表示法,由于VS是小端存放,所以我们看到的样子是倒着放到的,如果不太懂得同学可以看看 数据在计算机内部的存储 一文,里面有讲到大小端的相关知识
  • 那么右侧的就是一些参考信息,这一块可以不用理会

image.png

3.3 查看调用堆栈

  • 如果读者看过 C/C++内存分布 的话就可以知道在内存中存在着一个区域叫做【栈区】,也可以叫做【堆栈】

image.png

  • 为什么叫做堆栈呢?仔细看右侧的这个结构是不是和下面的函数布局main()test1()test2()test3()存在一些关系呢,就像是一个个地堆了上去
void test3()
{
  printf("hello debug\n");
}
void test2()
{
  test3();
}
void test1()
{
  test2();
}
int main(void)
{
  test1();
  return 0;
}
  • 不过,这么来看我们还看不到一些再底层的细节,此时我们就可以右击选择下面的这个【显示外部代码】,此时我们又可以看到多出来一些东西

image.png

  • 可以看到,在main函数的下面我们又看到了一些类似于main函数的东西,到这里如果你看过 函数栈帧创建和销毁 的话

image.png

  • 这里可以带读者通过调试来看看这个main函数的底层调用究竟是怎样的


相关文章
|
Linux API 数据安全/隐私保护
|
10月前
|
监控 Java 编译器
Java虚拟机调优指南####
本文深入探讨了Java虚拟机(JVM)调优的精髓,从内存管理、垃圾回收到性能监控等多个维度出发,为开发者提供了一系列实用的调优策略。通过优化配置与参数调整,旨在帮助读者提升Java应用的运行效率和稳定性,确保其在高并发、大数据量场景下依然能够保持高效运作。 ####
234 58
|
9月前
|
负载均衡 监控 定位技术
HTTP代理网速变慢的原因及优化策略
随着互联网技术的发展,使用HTTP动态代理IP的人越来越多。本文介绍了HTTP代理网速变慢的六个常见原因及解决方法,包括代理服务器的地理位置、带宽、服务器负载、网络拥塞、配置问题和数据加密解密时间。通过识别和解决这些问题,可以有效提升HTTP代理的网速。
359 10
|
10月前
|
安全 算法 Unix
深入浅出操作系统:从基础概念到实践应用
【10月更文挑战第22天】本文旨在以浅显易懂的语言,为读者揭开操作系统的神秘面纱。我们将从操作系统的基本概念出发,逐步深入其核心功能与设计哲学,并通过具体代码示例,展示操作系统如何在实际中发挥作用。无论你是计算机科学的学生,还是对技术有浓厚兴趣的爱好者,这篇文章都将为你提供一次轻松愉快的操作系统之旅。
168 4
|
11月前
|
机器学习/深度学习 并行计算 算法
GPU加速与代码性能优化:挖掘计算潜力的深度探索
【10月更文挑战第20天】GPU加速与代码性能优化:挖掘计算潜力的深度探索
|
11月前
|
机器学习/深度学习 人工智能 自然语言处理
LLMs 入门实战系列大全:LLMs应用、领域大模型介绍、大模型常见面经汇总
LLMs 入门实战系列大全:LLMs应用、领域大模型介绍、大模型常见面经汇总
LLMs 入门实战系列大全:LLMs应用、领域大模型介绍、大模型常见面经汇总
|
10月前
|
测试技术 开发者
自动化测试之美:打造高效软件质量保障体系
在软件开发的海洋中,自动化测试是那艘能够带领团队驶向高效率与高质量的帆船。通过本文,我们将揭开自动化测试的神秘面纱,探索如何构建一个强大的自动化测试框架,确保软件产品的稳定性和可靠性。从基础概念到实战应用,我们将一步步引导您理解并实现自动化测试策略,让您的代码更加健壮,让您的发布周期更加短暂。
155 0
|
11月前
|
自然语言处理 搜索推荐 关系型数据库
elasticsearch学习六:学习 全文搜索引擎 elasticsearch的语法,使用kibana进行模拟测试(持续更新学习)
这篇文章是关于Elasticsearch全文搜索引擎的学习指南,涵盖了基本概念、命令风格、索引操作、分词器使用,以及数据的增加、修改、删除和查询等操作。
213 0
elasticsearch学习六:学习 全文搜索引擎 elasticsearch的语法,使用kibana进行模拟测试(持续更新学习)
|
机器学习/深度学习 人工智能 自动驾驶
【人工智能】图像识别:计算机视觉领域的识别与处理资源概览
在快速发展的科技时代,计算机视觉(Computer Vision, CV)作为人工智能的一个重要分支,正深刻改变着我们的生活与工作方式。图像识别作为计算机视觉的核心任务之一,旨在让机器能够理解和解释数字图像或视频中的内容,进而执行诸如目标检测、图像分类、场景理解等复杂任务。本文将深入探讨图像识别领域的关键技术、常用数据集、开源框架及工具资源,为从事或关注该领域的专业人士提供一份全面的指南。
431 2