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

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

Vue 3 + WebSocket 实战:公司通知实时推送功能详解

&#x1f4e2; Vue 3 WebSocket 实战&#xff1a;公司通知实时推送功能详解 &#x1f4cc; 收藏 点赞 关注&#xff0c;项目中要用到推送功能时就不怕找不到了&#xff01; 实时通知是企业系统中常见的功能&#xff0c;比如&#xff1a;管理员发布通知后&#xff0c;所有用户…...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践&#xff0c;很多人以为AI已经强大到不需要程序员了&#xff0c;其实不是&#xff0c;AI更加需要程序员&#xff0c;普通人…...