常用的调试技巧(如何检测bug)(一)

简介: 常用的调试技巧(如何检测bug)

1. 什么是bug?

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


1944年世界上第一台计算机马克1号诞生,在世界上第一位女程序员格蕾丝-霍普接手下,顺利改造成马克二号,


1946年的一天,霍普敲代码的时候发现计算机发生了故障,就在马克二号的继电器触点里,找到了一只被夹扁的小飞蛾。


正是这只小虫子卡住了机器的运行。


霍普顺手将飞蛾夹在工作笔记里,而备注的意思是臭虫,正是这一奇怪的称呼,奠定了Bug这个词在计算机世界的地位,bug也变成无数苦逼工程师的噩梦。这就是第一个bug的诞生。


2. 调试是什么?有多重要?


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

一名优秀的程序员是一名出色的侦探。

       每一次调试都是尝试破案的过程

我们是如何写代码的?

76bfa4d82d0d446b938d6fe5b93be9e3.png

又是如何排查出现的问题的呢?

4e860b9d331d4281abfadf028c6673a0.png

拒绝-迷信式调试!!!!


2.1 调试是什么?

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


2.2 调试的基本步骤

发现程序错误的存在

以隔离、消除等方式对错误进行定位

确定错误产生的原因

提出纠正错误的解决办法

对程序错误予以改正,重新测试

2.3 Debug和Release的介绍。

Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。 Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优 的,以便用户很好地使用。


代码:

#include <stdio.h>
int main()
{
 char *p = "hello bit.";
 printf("%s\n", p);
 return 0;
}

上述代码在Debug环境的结果展示:

0c84807b88424b57b5d24154c9bce8ae.png

上述代码在Release环境的结果展示

78b2dbc36dac49849e7e6b0d3b3fbfbe.pngDebug和Release反汇编展示对比:

7a9dd6b866d141f2bca2a646cc47901e.png

所以我们说调试就是在Debug版本的环境中,找代码中潜伏的问题的一个过程。

那编译器进行了哪些优化呢?

请看如下代码:

#include <stdio.h>
int main()
{
    int i = 0;
    int arr[10] = {0};
    for(i=0; i<=12; i++)
   {
        arr[i] = 0;
        printf("hehe\n");
   }
    return 0;
}

如果是 debug 模式去编译,程序的结果是死循环。

如果是 release 模式去编译,程序没有死循环。

那他们之间有什么区别呢?

就是因为优化导致的。

25289a42d236492cb8bb7a7cbbf948e5.png

变量在内存中开辟的顺序发生了变化,影响到了程序执行的结果。

3. Windows环境调试介绍

       注:linux开发环境调试工具是gdb,后期课程会介绍。

3.1 调试环境的准备

867bfa05efe445819c27e4523c1986d6.png

在环境中选择 debug 选项,才能使代码正常调试。

3.2 学会快捷键

1fb9a6bba2df44babe0122d214fa2b9f.png

最常使用的几个快捷键:


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

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

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

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

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


想知道更多快捷键?点击我哟


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

3.3.1 查看临时变量的值 在调试开始之后,用于观察变量的值。

在调试开始之后,用于观察变量的值

2ad4fcca1a664b4d8b8a6d04ed09dfd2.png

3.3.2 查看内存信息

在调试开始之后,用于观察内存信息

f98164e0fff044258128fe726f43eca4.png

3.3.3 查看调用堆栈

4ac9fa0e2249477cb6aab9fd32f64d29.png

通过调用堆栈,可以清晰的反应函数的调用关系以及当前调用所处的位置

3.3.4 查看汇编信息

在调试开始之后,有两种方式转到汇编:

(1)第一种方式:右击鼠标,选择【转到反汇编】:

e6de1cbe48b54f0cbc735a4194e5591d.png

(2)第二种方式:

0104c9d29ef14cb5a754a8f7690180c3.png

可以切换到汇编代码。

3.3.5 查看寄存器信息

a110fb6f32b34de28ea7dbf936b1b20d.png

可以查看当前运行环境的寄存器的使用信息

相关文章
Windows下的CMake下载与安装
Windows下的CMake下载与安装
Windows下的CMake下载与安装
|
Linux 关系型数据库 Oracle
rhel7安装oracle数据库软件,compat-libstdc++-33缺失
Missing or Ignored package compat-libstdc++-33-3.2.3
6469 0
|
12月前
|
存储 关系型数据库 MySQL
MySQL性能优化指南
【10月更文挑战第16天】MySQL性能优化指南
1033 0
|
缓存 NoSQL Java
在 Spring Boot 应用中使用 Spring Cache 和 Redis 实现数据查询的缓存功能
在 Spring Boot 应用中使用 Spring Cache 和 Redis 实现数据查询的缓存功能
695 0
|
数据采集 SQL 分布式计算
|
SQL 资源调度 监控
Flink SQL性能优化实践
Apache Flink流处理性能优化指南:探索数据源读取并行度、状态管理、窗口操作的优化策略,包括设置默认并行度、使用RocksDB状态后端、调整窗口大小。调优方法涉及数据源分区、JOIN条件优化、使用Broadcast JOIN。注意SQL复杂度、并发控制与资源调度,如启用动态资源分配。源码层面优化自定义Source和Sink,利用执行计划分析性能瓶颈。异常检测与恢复通过启用检查点,监控任务性能。预处理数据、使用DISTINCT去重,结合UDF提高效率。选择高效序列化框架和启用数据压缩,优化网络传输和系统配置。处理数据倾斜,均衡数据分布,动态调整资源和任务优先级,以提升整体性能。
591 2
|
机器学习/深度学习 人工智能 运维
Web应用防火墙是什么?分享工作原理及部署建议
Web应用防火墙是什么?分享工作原理及部署建议
508 0
|
存储 Oracle 关系型数据库
Oracle系列之三:Oracle字符集
Oracle系列之三:Oracle字符集
|
人工智能 自然语言处理 安全
如何通过网关降低大模型的调用费用,并提升合规性
分散的 API 密钥将不利于组织进行 API 的用量计算、管理与付费,从而增加 AI 大模型的使用成本。
|
Ubuntu 程序员 Windows
Ubuntu+Windows双系统,开机默认启动项设置Windows优先
电脑是Ubuntu18.04+Win10双系统,开机一直都是默认先Ubuntu,Windows在最下面,有时候按下开机键一不留神就进Ubuntu了,于是寻思着在启动项中设置为默认优先Windows。
3096 0