实用调试技巧(一)

简介: 实用调试技巧

1、什么是bug?

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

感兴趣的小伙伴可以看一下下面这篇文章,链接放下面了。

注:

网络异常,图片无法展示
|

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

所有发生的事情都一定有迹可循,如果问心无愧,就不需要掩盖也就没有迹象了,如果问心有愧,
就必然需要掩盖,那就一定会有迹象,迹象越多就越容易顺藤而上,这就是推理的途径。
顺着这条途径顺流而下就是犯罪,逆流而上,就是真相。
一名优秀的程序员是一名出色的侦探。
每一次调试都是尝试破案的过程。
我们是如何写代码的?

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

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

2.1 调试是什么?

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

错误的一个过程。

2.2 调试的基本步骤

发现程序错误的存在

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

确定错误产生的原因

提出纠正错误的解决办法

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

2.3 Debug和Release的介绍。

 

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

 

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

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

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

Debug和Release反汇编展示对比:

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

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

请看如下代码:

1. #include <stdio.h>
2. int main()
3. {
4.  int i = 0;
5.  int arr[10] = { 0 };
6.  for (i = 0; i <= 12; i++)
7.  {
8.    arr[i] = 0;
9.    printf("hehe\n");
10.   }
11.   return 0;
12. }

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

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

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

就是因为优化导致的。

首先我们先看看在Debug中为什么会出现死循环:

1. #include <stdio.h>
2. int main()
3. {
4.  int i = 0;
5.  int arr[10] = { 0 };
6.  for (i = 0; i <= 12; i++)
7.  {
8.    arr[i] = 0;
9.    printf("hehe\n");
10.   }
11.   return 0;
12. }

从这段代码我们可以看到,数组会发生越界访问,这就导致了地址的不确定性。

通过调试我们发现:

在越界访问的过程中,arr[12]的值一直和i的值一样,说明了它们两个共用了同一个地址,所以在arr[12]=0的时候i又等于0了,循环重新开始,也就出现了死循环!!!

那么,在Release中则是对代码进行了优化。看它们两个的大小就可以看出来不同。

Release中是对代码中的变量的地址进行了更换,我们可以通过看i和arr[12]的地址得到:

经过Release 的优化后,两者的地址不一样了,就不会出现死循环了。


 

相关文章
|
2月前
|
程序员
调试技巧vs2022
调试技巧vs2022
|
2月前
|
C++
VS调试技巧
VS调试技巧
21 0
|
10月前
调试技巧(2)
调试技巧(2)
调试技巧(2)
|
10月前
|
网络协议 C++
继续分享 5 个实用的 vs 调试技巧
继续分享 5 个实用的 vs 调试技巧
|
11天前
|
NoSQL 程序员 Linux
实用调试技巧(1)
实用调试技巧(1)
22 7
|
2月前
|
程序员
关于MSVS的实用调试技巧
关于MSVS的实用调试技巧
34 0
|
7月前
|
安全 程序员 Windows
实用调试技巧
实用调试技巧
66 0
|
8月前
|
程序员 编译器
实用调试技巧(上)
实用调试技巧
|
11月前
|
程序员 C语言
|
数据采集 安全 程序员
实用调试技巧——“C”
实用调试技巧——“C”