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

初阶C语言——实用调试技巧【详解】

文章目录

  • 1. 什么是bug?
  • 2. 调试是什么?有多重要?
    • 2.1 调试是什么?
    • 2.2 调试的基本步骤
    • 2.3 Debug和Release的介绍
  • 3.学会使用快捷键
  • 4.调试的时候查看程序当前信息
    • 4.1 查看临时变量的值
    • 4.2 查看内存信息
    • 4.3 查看调用堆栈
    • 4.4 查看汇编信息
    • 4.5 查看寄存器信息
  • 5. 一些调试的实例
    • 5.1 实例一
    • 5.2 实例二
    • 5.3 大代码如何调试
  • 6. 如何写出好(易于调试)的代码
    • 6.1 优秀的代码:
    • 6.2 示范
    • 6.3 const的作用
  • 7. 编程常见的错误

1. 什么是bug?

bug是计算机领域专业术语,原意是臭虫。现在用来指代计算机上存在的漏洞。

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

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

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

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环境的结果展示:
在这里插入图片描述
上述代码在Release环境的结果展示:
在这里插入图片描述
在环境中选择 debug 选项,才能使代码正常调试。

3.学会使用快捷键

在这里插入图片描述
最常使用的几个快捷键:
F5

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

F9

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

F10

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

F11

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

CTRL + F5

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

Fn

辅助功能键

如果一个代码循环一千多次,而我们认为他的错误在四百次的地方时,要怎么调试?
这时我们就可以给他加一个触发断点的条件,或者使用一个if语句来进行判断。如下图所示:
在这里插入图片描述
在这里插入图片描述

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

通过调试下的窗口键来进行查看
在这里插入图片描述

4.1 查看临时变量的值

在调试开始之后,用于观察变量的值。
在这里插入图片描述

4.2 查看内存信息

在调试开始之后,用于观察内存信息。
在这里插入图片描述
显示内存结果:
在这里插入图片描述

4.3 查看调用堆栈

栈:
只能从顶上放入,再从顶上删除
在这里插入图片描述

在这里插入图片描述
通过调用堆栈,可以清晰的反应函数的调用关系以及当前调用所处的位置。

4.4 查看汇编信息

在这里插入图片描述
可以切换到汇编代码。

4.5 查看寄存器信息

在这里插入图片描述
可以查看当前运行环境的寄存器的使用信息。

5. 一些调试的实例

5.1 实例一

实现代码:求 1!+2!+3! …+ n! ;不考虑溢出。

#include <stdio.h>
int main()
{int i = 0;int sum = 0;//保存最终结果int n = 0;int ret = 1;//保存n的阶乘scanf("%d", &n);for (i = 1; i <= n; i++){int j = 0;for (j = 1; j <= i; j++){ret *= j;}sum += ret;}printf("%d\n", sum);return 0;
}

这时候我们如果3,期待输出9,但实际输出的是15
这时候我们就得通过调试找我们问题。
在这里插入图片描述

通过调试,我们发现问题出现在ret的值上,ret的值为每次结果值的累积效果,所以在循环内部令ret=1,结果就为我们想要的结果。

代码修改后:

#include <stdio.h>
int main()
{int i = 0;int sum = 0;//保存最终结果int n = 0;int ret = 1;//保存n的阶乘scanf("%d", &n);for (i = 1; i <= n; i++){ret = 1;int j = 0;for (j = 1; j <= i; j++){ret *= j;}sum += ret;}printf("%d\n", sum);return 0;
}

运行结果:
在这里插入图片描述

5.2 实例二

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

在这里插入图片描述
数组越界访问,我们发现程序并不会崩溃而是陷入死循环,这是为什么呢?
在这里插入图片描述
通过调试我们发现arr[12]与i的地址一样,改变arr[12]就改变了i
在这里插入图片描述

arr与i之间到底空几个空间取决于编译器的内存分配
vc6.0 中间没有空间
gcc 中间空一个整形
vs 中间空两个整形

注: 这个代码的运行结果是和环境相关的!

5.3 大代码如何调试

在这里插入图片描述
例如我们写过的三子棋,当出现问题时,我们可以在感觉有问题的模块放上断点来进行调试。

6. 如何写出好(易于调试)的代码

6.1 优秀的代码:

  1. 代码运行正常
  2. bug很少
  3. 效率高
  4. 可读性高
  5. 可维护性高
  6. 注释清晰
  7. 文档齐全

常见的coding技巧:

  1. 使用assert
  2. 尽量使用const
  3. 养成良好的编码风格
  4. 添加必要的注释
  5. 避免编码的陷阱

6.2 示范

模拟实现库函数:strcpy
strcpy
string copy —— 字符串拷贝

在这里插入图片描述
代码演示:

#include <stdio.h>
#include <assert.h>
//strcpy函数返回的是目标空间的起始地址char* my_strcpy(char* dest, const char* src)
{//断言 - 保证指针的有效性assert(dest && src);char* ret = dest;//把src指向的字符串拷贝到dest指向是的数组空间,包括\0字符while (*dest++ = *src++){;}return ret;
}int main()
{char arr1[] = "hello world";char arr2[20] = { 0 };//链式访问printf("%s\n", my_strcpy(arr2, arr1));return 0;
}

6.3 const的作用

代码演示:

#include <stdio.h>
//代码1
void test1()
{int n = 10;int m = 20;int* p = &n;*p = 20;//ok?p = &m; //ok?printf("%d\n", m);
}
void test2()
{//代码2int n = 10;int m = 20;const int* p = &n;p = &m; //ok//*p = 20;//noprintf("%d\n", m);
}
void test3()
{int n = 10;int m = 20;int* const p = &n;*p = 20; //ok//p = &m; //noprintf("%d\n", m);
}
int main()
{//测试无cosnt的test1();//测试const放在*的左边test2();//测试const放在*的右边test3();return 0;
}

结论:
const修饰指针变量的时候:

  1. const 放在*的左边, *p不能改了,也就是p指向的内容,不能通过p来改变了。但是p是可以改变的,p可以指向其他的变量
  2. const 放在的右边,限制的是p,p不能改变,但是p指向的内容p,是可以通过p来改变的

练习:

模拟实现一个strlen函数
参考代码:

#include <stdio.h>
#include <assert.h>
int my_strlen(const char* str)
{int count = 0;assert(str != NULL);while (*str)//判断字符串是否结束{count++;str++;}return count;
}
int main()
{const char* p = "abc";//测试int len = my_strlen(p);//strlen函数求\0之前字符串的长度printf("len = %d\n", len);return 0;
}

7. 编程常见的错误

1.编译型错误

接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单。

例如语句后的分号
在这里插入图片描述

2. 链接型错误

看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不
存在或者拼写错误。

例如:
在这里插入图片描述

3.运行时错误

借助调试,逐步定位问题。最难搞。

关于调试技巧的讲解七七就分享到这了,有什么问题或者需要改进的地方欢迎评论区留言,或者私信都可以哦!

相关文章:

初阶C语言——实用调试技巧【详解】

文章目录1. 什么是bug&#xff1f;2. 调试是什么&#xff1f;有多重要&#xff1f;2.1 调试是什么&#xff1f;2.2 调试的基本步骤2.3 Debug和Release的介绍3.学会使用快捷键4.调试的时候查看程序当前信息4.1 查看临时变量的值4.2 查看内存信息4.3 查看调用堆栈4.4 查看汇编信息…...

Android 绘图基础:Canvas画布——自定义View基础(绘制表盘、矩形、圆形、弧、渐变)

Canvas画布&#xff0c;通过它我们可以自定义一个View&#xff0c;设置View的相关效果之类的。感觉用法差不多&#xff0c;重要的是要理解方法中传入的参数的含义&#xff0c;比如float类型的参数&#xff0c;传递的是坐标,已开是没有注意传入的参数时坐标&#xff0c;导致我迷…...

js拷贝数组对象:浅拷贝深拷贝

前言 js拷贝数组对象&#xff1a;浅拷贝&深拷贝&#xff0c;包括&#xff1a;Object.assign、concat、slice、JSON.parse(JSON.stringify()) 场景&#xff1a;弹窗选择组织结构&#xff08;树形结构&#xff09;&#xff0c;选择后显示相关数据至输入框中&#xff08;每次选…...

【C++】string类的使用

目录 一、标准库中的string类 二、string类的常用接口 1、string类对象的常见构造 2、string类对象的容量操作 2.1、size 与 length 2.2、capacity 与 reserve 2.3、resize 2.4、总结 3、string类对象的访问及遍历操作 3.1、operator[] 与 at 3.2、begin end 3.3、…...

微服务架构简介

微服务 软件架构是一个包含各种组织的系统组织&#xff0c;这些组件包括 Web服务器, 应用服务器, 数据库,存储, 通讯层), 它们彼此或和环境存在关系。系统架构的目标是解决利益相关者的关注点。 image Conway’s law: Organizations which design systems[...] are constrained…...

【Spring源码】AOP的开端:核心对象创建的准备工作

AOP的核心成员是如何被被加载的&#xff1f;本篇我们主要分析使用xml的逻辑&#xff0c;如果使用注解&#xff0c;增加注解处理类即可&#xff08;ConfigurationClassPostProcessor&#xff09;拿之前分析循环的时候举的例子&#x1f330;&#xff0c;它的日志切面就是通过xml进…...

新号涨粉22w,搞笑博主再次爆火,小红书近期创作趋势是什么?

2月借势元宵、情人节&#xff0c;小红书平台又涌现出哪些黑马博主&#xff1f;品牌在投放种草方面有何亮眼表现&#xff1f;为洞察小红书平台的内容创作趋势及品牌营销策略&#xff0c;新红推出2月月度榜单&#xff0c;从创作者及品牌两方面入手&#xff0c;解析月榜数据&#…...

【C++】30h速成C++从入门到精通(内存管理、函数/类模板)

C内存分布我们先来看一下下面的一段代码相关问题int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";char* pChar3 "abcd";int* ptr1 (int*)mal…...

自动驾驶决策概况

文章目录1. 第一章行为决策在自动驾驶系统架构中的位置2. 行为决策算法的种类2.1 基于规则的决策算法2.1.1 决策树2.1.2 有限状态机&#xff08;FSM&#xff09;2.1.3 基于本体论&#xff08;Ontologies-based&#xff09;2.2 基于统计的决策算法2.2.1 贝叶斯网络&#xff08;B…...

金山轻维表项目进展自动通知

项目经理作为项目全局把控者&#xff0c;经常要和时间“赛跑”。需要实时了解到目前进展如何&#xff0c;跟进人是那些&#xff1f;哪些事项还未完成&#xff1f;项目整体会不会逾期&#xff1f;特别是在一些大型公司中&#xff0c;优秀的项目经理已经学会使用金山轻维表做项目…...

基于上下文分析的 Python 实时 API 推荐

原文来自微信公众号“编程语言Lab”&#xff1a;基于上下文分析的 Python 实时 API 推荐 搜索关注 “编程语言Lab”公众号&#xff08;HW-PLLab&#xff09;获取更多技术内容&#xff01; 欢迎加入 编程语言社区 SIG-程序分析 参与交流讨论&#xff08;加入方式&#xff1a;添加…...

软件测试-接口测试-代码实现接口测试

文章目录 1.request1.1 request介绍1.2 发送get请求1.3 发送set请求1.4 其他请求方式1.5 传递url参数1.6 响应内容解析1.7 cookie1.8 设置session2.集成UnitTest2.1 接口测试框架开发2.2 案例:使用TPShop项目完成对登录功能的接口测试1.request 1.1 request介绍 概念 基于py…...

中村成洋《垃圾回收的算法与实现》PDF 读书笔记

观前提醒 为了能够锻炼自己&#xff0c;我会查阅大量外文不停的修改内容&#xff0c;少部分会提示成中文。 可能有误&#xff0c;请见谅 提示&#xff1a;若是觉得阅读困难&#xff0c;可以看如下内容 脚本之家可获取&#xff0c;若失效可私信浏览器的沙拉查词扩展&#xf…...

docker 网络模式

docker 网络模式主要分为四种&#xff0c;可以通过docker network ls 查看 ~$ docker network ls NETWORK ID NAME DRIVER SCOPE a51d97d72f10 bridge br…...

数据库开发(一文概括mysql基本知识)

Mysql 是最流行的关系型数据库管理系统&#xff0c;在 WEB 应用方面 MySQL 是最好的 关系型数据库(Relational Database Management System&#xff1a;关系数据库管理系统)应用软件之一。mysql在问开发中&#xff0c;几乎必不可少&#xff0c;因为其他的可能是要收费的&#x…...

【JVM】详解Java内存区域和分配

这里写目录标题一、前言二、运行时数据分区2.1程序计数器(PC)2.2 Java虚拟机栈2.3 本地方法栈2.4 Java堆2.5 方法区2.5.1 运行时常量池2.6 直接内存三、HotSpot虚拟机对象探秘3.1 对象的创建3.2 对象的内存布局3.3 对象的访问定位一、前言 C/C需要自行回收和释放已经没用的对象…...

JAVA开发(史上最完整追本溯源JAVA历史、发展和学习)

(第二次世界大战1931-1945) 世界上最先进的技术往往是由于战争催生&#xff0c;在第二次世界大战中除了飞机&#xff0c;坦克和大炮的武器较量外&#xff0c;在隐秘战线的情报工作其实更为重要&#xff0c;在军队将领来往的电报中&#xff0c;为了防止军事情报的泄漏&#xff…...

Qt 防止程序退出

文章目录摘要QWidgetQML方法 1方法 2关键字&#xff1a; Qt、 eventFilter、 Close、 键盘、 任务管理器摘要 今天要聊得内容还是怎么防止别人关闭我的程序&#xff0c;之前都是在win下面&#xff0c;一般都是用过钩子连捕获键盘事件&#xff0c;完了吧对应的事件忽略&#x…...

【校验码 - 循环冗余校验码CRC】

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 目录 循环冗余校验码 1.多项式 2.CRC编码的组成 3.校验码的生成 4.例题&#xff1a; 循环冗余校验码 广泛地在网络通信及磁盘存储时采用。 1.多项式 在循环冗余校验(CRC)码中&#xff0c;无一例…...

【Rust】一文讲透Rust中的PartialEq和Eq

前言 本文将围绕对象&#xff1a;PartialEq和Eq&#xff0c;以及PartialOrd和Ord&#xff0c;即四个Rust中重点的Compare Trait进行讨论并解释其中的细节&#xff0c;内容涵盖理论以及代码实现。 在正式介绍PartialEq和Eq、以及PartialOrd和Ord之前&#xff0c;本文会首先介绍…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统

Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...