了解bug以及如何解决bug------调试(使用技巧)(下)

简介: 了解bug以及如何解决bug------调试(使用技巧)

四、调试示例

(一个经典的笔试题)

代码如下:

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

上面的代码,很直观的一个错误是数组发生了越界访问,这个错误会影响我们正常打印"haha"吗,如果打印会打印几个"haha"呢?

或许大家会认为打印12个"haha",但事实如此吗?

我们将这个代码运行一下:

可以看到,这个程序是死循环的打印"haha"而非只打印12个"haha"。

为什么会出现这种情况呢?

我们对这个程序进行调试观察变量中的内容以及地址信息

调试过程中发现,数组越界访问到的arr[12]和变量i的值是一起变化的,而当数组越界访问到arr[12]并将arr[12]赋值为0时,i的值也变为了0.

观察arr[12]和变量i的内存地址我们发现他们的地址是相同的,即这个程序中数组的越界访问,恰好访问到了变量i的内存空间,改变arr[12]就是改变变量i。

因此循环的条件i<=12是永远都会满足,程序变成了死循环。

下面我来简单说明一下出现这种情况的原因:

①数组arr和变量i都是放在栈区的;

②栈区的使用习惯是先用高地址再使用低地址(由高向低),因此先创建的变量i的地址会比数组arr的地址高;

③数组随着下标的增长,地址是从低地址向高地址变化的 (由低向高);

因此数组arr越界访问到arr[12]时,正好访问了变量i的空间。

(这是在vs空间上的特殊情况,其他编译器中数组和变量之间的空间不一定是2:例如在VC6.0中,变量i和数组arr之间是没有空间的,而在gcc中变量i和数组arr之间空出一个int的空间。)

五、如何写出优秀(易于调试)的代码?

1.优秀的代码

1.代码运行正常

2.Bug少

3.效率高

4.可读性高

5.可维护性高

6.注释清晰

7.文档齐全

2.常见的coding技巧

1.使用assert

断言:编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式。

2.使用const

1.用const修饰变量时,该变量的值就不能再被赋值,除非使用存有该变量地址的指针直接通过地址访问该变量。

2.用const修饰指针变量时:

(1)const放在*左边(eg:const int *p;),修饰的是该指针指向的内容,用来确保该指针指向的内容不会通过该指针修改;

(2)const放在*右边(eg:int * const p;),修饰的是指针变量本身,保证了指针变量的内容不会被修改,而该指针变量指向的内容可以通过该指针来修改。

3.有一个良好的代码风格

变量的命名、代码的编写格式、代码的整齐度……

增强代码的可读性,方便自己和其他人读懂代码。

4.添加必要的注释

对必要的内容进行注释,例如所创建的函数的功能、变量的含义、程序的头文件中的内容……

增强代码的可读性,方便自己和其他人读懂代码。

5.避免编码的陷阱

空指针、野指针的错误解引用……

3.示例

用C语言编写代码实现库函数strcpy(下图是运行结果,对自己实现的my_strcpy和库函数的strcpy进行了比较,两者结果是相同的)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
#include<string.h>
//strcpy是一个库函数,strcpy把含有'\0'结束符的字符串复制到另一个地址空间,返回值的类型为char*。
//将源变量的内容拷贝放置进目标变量
//这个函数是将src的值拷贝到dst中,为了避免出现将dst的值拷贝到src这种错误,可以用const修饰src
//形参名具有一定意义,便于识别
char * my_strcpy(char * dst, const char * src) 
{
  char * cp = dst;
  assert(dst && src);//用assert判断函数传参传过来的是否是空指针,避免出现空指针的解引用
  while (*cp++ = *src++)
    ;   
  return(dst);
}
int main()
{
  char arr1[] = "abcdef";
  char arr2[] = "ghi";
  my_strcpy(arr1, arr2);
  printf("%s\n",arr1);
  strcpy(arr1, arr2);
  printf("%s\n", arr1);
  return 0;
}

六、小彩蛋

      最初的计算机键盘上的等按键都是自己本身的功能,但随着计算机的不断发展,企业、家庭、个人都能够使用计算机。为了方便用户对计算机的使用,生产方就给赋予了新的功能,比如调节屏幕亮度、调节音量大小等等。

      那么如何使用他们本身的功能呢?这里给大家两种方法:

  1. 一般键盘上会有一个按键,用+就可以使用本身的功能,即运行程序到断点处。(其他按键的使用和它类似)
  2. 在计算机的设置中关闭的功能(由于每个人电脑型号系统都不同,作者不能列举出每一种方法,所以具体操作方法可以在百度上自行搜索)。


总结

       以上就是今天要讲的内容,本文简单的介绍了bug和调试的概念,还进一步用实例演示了如何通过调试来找到bug并且解决它。

       本文的作者也只是一个正在学习C语言等编程知识的萌新,若这篇文章中有哪些不正确的内容,请在评论区向作者指出(也可以私信作者),欢迎大佬们指点,也欢迎其他正在学习C语言的萌新和作者进行交流。

       最后,如果本篇文章对你有所启发的话,也希望可以支持支持作者,后续作者也会定期更新学习记录。谢谢大家!


相关文章
|
人工智能 自然语言处理 云计算
阿里云再获中国游戏云市场份额第一
国际数据公司(IDC)最新发布的《中国游戏云市场跟踪》报告显示,2023全年中国游戏云整体市场规模达到123亿元人民币,阿里云连续两年稳居中国游戏云整体市场份额第一。其中,游戏云基础设施(IaaS)+云解决方案(Cloud Solution)市场共计102亿,阿里云优势更为突出,市场份额提升至39%。
|
SQL 监控 关系型数据库
PostgreSQL普通表转换成分区表
如何使用pg_rewrite扩展将普遍表转换成分区表
|
数据可视化 持续交付 开发工具
RAD技术解析:快速开发应用程序的秘诀
**快速应用开发(RAD)**是一种始于90年代的敏捷方法,旨在通过迭代原型和反馈加速高质量软件交付。由James Martin提出,它包括需求规划、界面设计、快速构建和持续优化四阶段,以提高质量、降低风险、增强灵活性、降低成本和提升客户满意度。工具如ZohoCreator支持RAD,通过可视化工具和低代码平台促进高效开发,实现快速迭代和市场适应,降低项目失败风险,提高用户满意度。
342 9
|
存储 数据处理 对象存储
R语言-稀疏矩阵对象格式介绍&重构方法
在单细胞领域,基于稀疏矩阵对于处理 scRNA-seq 表达谱数据这类大型数据是非常必要的,因为构建分析对象的时候稀疏矩阵相比稠密矩阵拥有更高的数据处理效率和速度。本文重点介绍 在R语言平台关于 Matrix包中Sparse Matrix对象的格式, 与Dense Matrix的转换以及重构方法。
1047 0
R语言-稀疏矩阵对象格式介绍&重构方法
|
负载均衡 监控 应用服务中间件
Nginx极简实战—如何实现Nginx负载均衡高可用
之前讲了Nginx 如何实现负载均衡,以及如何实现动静分离。但是还确少Nginx 高可用的部分。因为Nginx 处于整个系统非常重要的位置,Nginx的高可用影响到整个系统的稳定性。如果nginx服务器宕机后端web服务将无法提供服务,影响严重。所以,接下来就来介绍Nginx + keepalived 实现高可用的方案。
Nginx极简实战—如何实现Nginx负载均衡高可用
|
Java 测试技术 数据库
Java Spring Boot: 极简配置与快速开发的利器
Java Spring Boot: 极简配置与快速开发的利器
|
SQL JSON 关系型数据库
PostgreSQL安装、配置及简单使用方法
一、PostgreSQL简介 1、什么是PostgreSQL PostgreSQL数据库是目前功能最强大的开源数据库,支持丰富的数据类型(如JSON何JSONB类型,数组类型)和自定义类型。而且它提供了丰富的接口,可以很容易地扩展它的功能,如可以在GiST框架下实现自己的索引类型等,它还支持使用C语言写自定义函数、触发器,也支持使用流行的语言写自定义函数,比如其中的PL/Perl提供了使用Perl语言写自定义函数的功能,当然还有PL/Python、PL/Tcl,等等。 2、PostgreSQL数据库的优势 PostgreSQL数据库是目前功能最强大的开源数据库,它是最接近工业标准SQL
2076 0
|
缓存 运维 NoSQL
中泰证券引入阿里云瑶池数据库
中泰证券引入阿里云瑶池数据库
256 0
|
4天前
|
弹性计算 运维 搜索推荐
三翼鸟携手阿里云ECS g9i:智慧家庭场景的效能革命与未来生活新范式
三翼鸟是海尔智家旗下全球首个智慧家庭场景品牌,致力于提供覆盖衣、食、住、娱的一站式全场景解决方案。截至2025年,服务近1亿家庭,连接设备超5000万台。面对高并发、低延迟与稳定性挑战,全面升级为阿里云ECS g9i实例,实现连接能力提升40%、故障率下降90%、响应速度提升至120ms以内,成本降低20%,推动智慧家庭体验全面跃迁。