当前位置: 首页 > 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;本文会首先介绍…...

Linux桌面便签工具终极指南:Sticky如何重新定义你的信息管理方式

Linux桌面便签工具终极指南&#xff1a;Sticky如何重新定义你的信息管理方式 【免费下载链接】sticky A sticky notes app for the linux desktop 项目地址: https://gitcode.com/gh_mirrors/stic/sticky 你是否曾在忙碌的工作中突然闪现一个灵感&#xff0c;却因为切换…...

php artisan serve 在window上执行报错的问题

今天偶发想学习一下Laravel 当执行 php artisan serve 结果一直没法起来 报错信息如下所示&#xff1a; 当前php 环境为 8.2.9 php -v解决办法&#xff1a; php -S localhost:9999 -t public...

VMware解锁macOS完整指南:3步免费运行苹果系统

VMware解锁macOS完整指南&#xff1a;3步免费运行苹果系统 【免费下载链接】unlocker VMware Workstation macOS 项目地址: https://gitcode.com/gh_mirrors/unloc/unlocker 你是否渴望在Windows或Linux电脑上体验macOS的魅力&#xff1f;无论你是开发者需要测试iOS应用…...

保姆级教程:用树莓派+罗技C310搭建简易监控(附fswebcam完整参数表)

树莓派罗技C310搭建智能监控系统的完整实践指南 在智能家居和远程办公日益普及的今天&#xff0c;搭建一个低成本、高灵活性的监控系统已经成为许多技术爱好者的需求。本文将带你从零开始&#xff0c;利用树莓派和罗技C310 USB摄像头构建一个功能完善的监控解决方案。不同于市面…...

三菱FX3U串口通讯无协议编程与RS指令实现Modbus协议

引言 在工业自动化系统中&#xff0c;PLC与上位机之间的通讯至关重要。Modbus RTU协议 作为一种广泛应用的通讯协议&#xff0c;通常用于不同设备之间的数据交换。 对于三菱 FX3U系列PLC 来说&#xff0c;虽然它没有直接内置完整的Modbus RTU从站功能&#xff08;早期型号需通过…...

SkillForge:构建可复用技能模块的标准化框架与实践指南

1. 项目概述与核心价值 最近在开源社区里&#xff0c;一个名为 SkillForge 的项目引起了我的注意。它的仓库地址是 kographh/skillforge &#xff0c;这个名字本身就很有意思——“技能锻造”。作为一名长期在技术一线摸爬滚打的开发者&#xff0c;我见过太多号称能“提升效…...

别再搞混了!海康威视工业相机SDK和安防SDK开发环境配置避坑指南(VS2019+MVS3.2)

海康威视工业相机开发避坑指南&#xff1a;从硬件选型到SDK环境配置全解析 第一次接触海康威视工业相机的开发者&#xff0c;往往会被网上铺天盖地的安防相机教程带偏方向。我曾亲眼见过团队花费三天时间尝试用iVMS-4200客户端激活一台根本不需要密码的工业相机&#xff0c;也调…...

STM32 LWIP服务器内存泄漏踩坑实录:我是如何实现多客户端连接并稳定运行72小时的

STM32 LWIP服务器内存泄漏排查与多客户端连接优化实战 在嵌入式网络应用中&#xff0c;STM32结合LWIP协议栈构建TCP服务器是常见方案。但当系统需要支持多客户端并发连接并长期运行时&#xff0c;内存管理问题往往成为稳定性的最大威胁。本文将分享一个真实案例&#xff1a;如何…...

保姆级教程:在Ubuntu 20.04上用YOLOv5 v6.2训练你自己的COCO数据集(附完整数据准备流程)

在Ubuntu 20.04上从零构建YOLOv5 v6.2自定义训练环境的完整指南 当你想在本地工作站或云服务器上训练自己的目标检测模型时&#xff0c;YOLOv5无疑是最受欢迎的选择之一。但许多教程都假设你已经熟悉了Linux环境配置、数据集处理等前置知识&#xff0c;这让不少初学者在第一步…...

3分钟掌握B站缓存视频转换:m4s-converter让你的视频永久保存

3分钟掌握B站缓存视频转换&#xff1a;m4s-converter让你的视频永久保存 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾经遇到过这样的…...