C语言调试大作战:与VS编译器共舞,上演一场“捉虫记”的艺术与科学

少年们好,我是博主那一脸阳光,我们接下来介绍C语言的调试和bug的分享。
引言:
“如果你曾经在深夜与一串神秘莫测的C代码狭路相逢,彼此瞪大眼睛,犹如牛仔对决般紧张刺激;或者你曾试图驯服一段狂野不羁的循环,却发现自己陷入了一个深不见底的逻辑黑洞,那么恭喜你,你已经正式加入了C语言调试者联盟!在这个奇妙的编程世界里,我们可不是简单的码农,更像是手持放大镜和捕虫网的侦探,以寻找并消灭那些狡猾又隐秘的’小bug’为己任。今天,让我们一同展开这场充满笑声与泪水、挫折与突破的C语言调试奇幻之旅,看看那些让程序员们既爱又恨的’小家伙们’是如何诞生,又是如何被我们智勇双全地一一拿下!”

关于BUG的由来和故事

"Bug"一词在计算机领域的起源,与硬件故障和软件缺陷有着紧密联系。关于这个词的由来,有两种广为流传的故事:

硬件故障导致的“虫子”事件:

其中一个故事追溯到早期计算机的时代,具体时间大约在20世纪40年代末至50年代初。这个故事描述的是美国哈佛大学的马克-II(Mark II)电子管计算机发生的一次故障。1947年9月9日,计算机科学家格蕾丝·赫柏(Grace Hopper)在检查这台机器时发现了一个由于飞蛾误入继电器触点而引发的故障。工作人员把这只飞蛾从设备中取出,并把它粘贴在了日志本上,旁边标注着“First actual case of bug being found”(首次发现实际的bug)。从此,“bug”开始被广泛用来指代计算机系统中的错误或故障。
工程术语的沿用:

另一个版本的历史背景更为久远,甚至早于计算机的发明。在电气工程和其他工程领域,早在19世纪,“bug”就已经作为行话使用,用来描述机械设备中的小故障或设计问题。托马斯·爱迪生(Thomas Edison)在他的个人通信中就曾使用过“bug”来形容技术问题。当计算机出现后,这个术语自然而然地过渡到了新兴的计算机科学领域,继续用于表示程序或硬件的错误。
无论是哪种起源,最终“bug”成为了软件开发和信息技术行业内的通用词汇,用来指代程序代码中导致程序行为异常的问题。相应的,“debugging”即调试,指的是寻找并修复这些程序错误的过程。

在这里插入图片描述

什么是调试(debug)

当我们发现程序中存在的问题的时候,那下⼀步就是找到问题,并修复问题。
这个找问题的过程叫称为调试,英⽂叫debug(消灭bug)的意思。
调试⼀个程序,⾸先是承认出现了问题,然后通过各种⼿段去定位问题的位置,可能是逐过程的调
试,也可能是隔离和屏蔽代码的⽅式,找到问题所的位置,然后确定错误产⽣的原因,再修复代码,
重新测试。

Debug和Release

在这里插入图片描述
在VS上编写代码的时候,就能看到有 debug 和 release 两个选项,分别是什么意思呢
Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序;
程序员在写代码的时候,需要经常性的调试代码,就将这⾥设置为 debug ,这样编译产⽣的是
debug 版本的可执⾏程序,其中包含调试信息,是可以直接调试的。
Release 称为发布版本,它往往是进⾏了各种优化,使得程序在代码⼤⼩和运⾏速度上都是最优的,
以便⽤⼾很好地使⽤。当程序员写完代码,测试再对程序进⾏测试,直到程序的质量符合交付给⽤⼾
使⽤的标准,这个时候就会设置为 release ,编译产⽣的就是 release 版本的可执⾏程序,这个
版本是⽤⼾使⽤的,⽆需包含调试信息等。
在这里插入图片描述对⽐可以看到从同⼀段代码,编译⽣成的可执⾏⽂件的⼤⼩,release版本明显要⼩,⽽debug版本明
显⼤。

VS牛仔侦探福尔摩斯的快捷键西部抓“BUG”大戏

欢迎来到编程世界的狂野西部,这里的治安官不叫警长,而是一位身怀绝技的“VS牛仔侦探福尔摩斯”。他以Visual Studio为马鞍,代码行作为疆界,手握一连串神奇的快捷键法器,誓要在这片充满神秘bug的边陲之地,上演一场又一场惊心动魄、笑料百出的抓“小偷”(BUG)好戏。

当夜幕降临,小镇沉睡,罪恶悄然滋生。别慌,瞧!我们的“VS牛仔侦探福尔摩斯”已经整装待发:

F9:设置断点,犹如布下天罗地网 —— 就像牛仔在小偷必经之路埋伏设陷阱,等待他们自投罗网;

F10:逐过程追踪,玩转逻辑迷宫 —— 福尔摩斯抽着烟斗,步步为营,每按一下F10就如同推开一扇门,揭示下一个可能藏匿犯罪线索的房间;

F11:步入函数内部,深挖地下暗道 —— 牛仔侦探奋不顾身跳入深深的洞穴,钻进函数的核心地带,挖掘那些潜藏最深的小bug;

F5:启动调试列车,全速追捕逃犯 —— 随着一声汽笛长鸣,搭载着智慧与勇气的F5列车疾驰而出,直奔目标,将那些试图逃脱的小bug逮个正着!

还有那神秘的Ctrl+5,这可是牛仔侦探的秘密武器,它如同瞬间移动到任意场景的魔法帽,让侦探能够迅速切换至第五个监视窗口,随时洞察案发现场的每个角落,确保任何蛛丝马迹都无处遁形。

准备好你的键盘和鼠标,跟随这位集西部牛仔的勇猛与福尔摩斯般智谋于一身的“VS牛仔侦探福尔摩斯”,踏上这场风趣幽默、紧张刺激的编程西部冒险,看他是如何运用这些神奇快捷键,在虚拟世界中惩治邪恶,维护程序正义的吧!
总结:
那程序员怎么调试代码呢?
F9:创建断点和取消断点
断点的作⽤是可以在程序的任意位置设置断点,打上断点就可以使得程序执⾏到想要的位置暂定执
⾏,接下来我们就可以使⽤F10,F11这些快捷键,观察代码的执⾏细节。
条件断点:满⾜这个条件,才触发断点
F5:启动调试,经常⽤来直接跳到下⼀个断点处,⼀般是 和F9配合使⽤。
F10:逐过程,通常⽤来处理⼀个过程,⼀个过程可以是⼀次函数调⽤,或者是⼀条语句。
F11:逐语句,就是每次都执⾏⼀条语句,但是这个快捷键可以使我们的执⾏逻辑进⼊函数内部。在函数调⽤的地⽅,想进⼊函数观察细节,必须使⽤F11,如果使⽤F10,直接完成函数调⽤。
CTRL + F5:开始执⾏不调试,如果你想让程序直接运⾏起来⽽不调试就可以直接使⽤。

实际的使用

在这里插入图片描述
我们发现加了断点以后,调试的时候,居然跳过了断点前的代码,这样通过断点减少了程序员遇到的问题,想象一下有一万行代码前五千行代码都没得问题,如果一行一行调试即使你摁F10速度再快依旧需要很长时间,但是我们有了断点以后发现了节省了很多时间,让程序员对修改代码,查找的bug方式给方便和简洁。

F10的使用和F11的使用

在这里插入图片描述
F10:是过程意思是说,它会一条一条往下执行到了,test哪里它不会进入函数的内部而是直接算出结果,
F11:F11就是可以进入函数的内部一条一条的进行调试以及使用。 ``F11比F10更注重细节。

不调试代码直接执行用CTRL+F5即可

监视以及断点的实际应用

在这里插入图片描述C语言通过监视窗口可以看到i是如何递增的,在正常情况下这段代码i会打印到9以后,因为不满足接下来的循环条件而结束循环,但是如果我们想看第八次循环呢?那么是不是摁F10来实现呢?这里就需要了F9断点加上限制条件以及使用。

在这里插入图片描述
设计条件即可,这时候我们摁F10开始调试以后,我们就可以看到i从八开始进行打印以及循环的使用。

编程界的福尔摩斯

欢迎来到编程界的伦敦贝克街221B,只不过这里的侦探并非那位叼着烟斗、手持放大镜的福尔摩斯先生,而是我们英勇无畏的“VS福尔摩斯”。在这个由代码构筑的城市里,小偷不再偷金银珠宝,他们专偷程序的稳定性和效率——这些捣蛋鬼就是我们俗称的"BUG"。

我们的主人公“VS福尔摩斯”,凭借其无所不能的Visual Studio监视器和内存检查工具两大法宝,在错综复杂的函数丛林中游刃有余。他用监视器如鹰眼般精准定位每个变量的一举一动,通过内存观察则像显微镜一样洞察那些隐匿在数据结构深处的小bug们。

每当夜幕降临,城市陷入宁静,程序员们的噩梦却悄然开始。然而,不用担心,因为“VS福尔摩斯”已整装待发,他以调试窗口为笔记本,以断点为陷阱,挥舞着单步执行的大侦探手杖,誓要将每一个企图破坏代码和谐的小bug“窃贼”捉拿归案。

这段充满欢笑与智慧的抓“贼”故事即将上演,让我们跟随“VS福尔摩斯”的脚步,一同踏上这场妙趣横生又充满挑战的编程冒险之旅,看他是如何利用强大的VS工具,如同现实世界中的福尔摩斯那样,破解一个个看似无解的编程谜团,将那些令人头疼不已的小bug“小偷”一网打尽!
比如:`

#include <stdio.h>`
int main()
{int arr[10] = { 0 };int num = 100;char c = 'w';int i = 0;for (i = 0; i < 10; i++){arr[i] = i;}return 0;
}

我们来分析一下上面的代码```c
#include <stdio.h>

这一行是预处理器指令,它告诉编译器在编译之前先包含stdio.h头文件。stdio.h(Standard Input Output)包含了标准输入输出函数的声明,例如 printf() 和 scanf() 等。虽然在这个示例中并未使用这些函数,但在实际编程中,我们通常会包含这个头文件以备后续可能的输入输出操作。

C
int main()
{

main() 函数是 C 语言程序执行的起点,它是程序的入口点。main() 返回一个整数值,用来表示程序的退出状态,0 表示正常结束。

Cint arr[10] = { 0 };

这里声明了一个具有10个元素的一维整数数组 arr,并使用初始化列表 { 0 } 初始化所有元素为0。实际上,只给一个初始值时,C语言会将剩余的元素也默认初始化为该初始值,所以数组 arr 的所有元素都被初始化为0。

Cint num = 100;char c = 'w';

接着声明了两个变量:一个整型变量 num 赋值为100,另一个字符型变量 c 赋值为字符 ‘w’。不过,在这段代码片段中,这两个变量没有被进一步使用,它们可能是为了展示如何声明和初始化不同类型的变量。

Cint i = 0;

声明并初始化一个整数变量 i 作为循环计数器,它的初始值设为0。

Cfor (i = 0; i < 10; i++){arr[i] = i;}

这是一个经典的for循环结构。循环从 i 为0开始,每次循环迭代都会递增 i 的值,直到 i 不再小于10为止。在循环体内,数组 arr 的每个元素通过下标 i 被赋值为当前 i 的值。因此,当循环结束后,数组 arr 的内容将是 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]。

Creturn 0;
}

最后,main() 函数返回0,表明程序已成功执行完毕且无错误。

综上所述,此段C语言代码的主要功能是对一个大小为10的整数数组 arr 进行初始化,使得其存储从0到9的连续整数。同时展示了如何声明和初始化其他类型(如整型和字符型)的变量,尽管在这段特定代码中它们未被实际使用。
在这里插入图片描述
好,我们接下来来观察一下内存。

在这里插入图片描述
很多少年在这里看不懂了,这是什么啊,这其实就是内存的一个分配,这设计到一个东西叫做函数栈帧后期会给大家分享,剩下就是我们如何理解这个内存呢?我们在地址处输入arr,arr是一个数组,数组本身就是一个地址,正常要用&操作符的,但是arr是一个数组所以不需要。

调试举例

求 1!+2!+3!+4!+…10! 的和,我们知道阶乘的公式是要求1!+2!+3!+4!+…+10!的和,首先我们明确阶乘(Factorial)的定义:对于任意正整数n,n!表示的是所有小于等于n且大于0的整数的乘积。

公式如下: n! = 1 * 2 * 3 * … * (n-1) * n

所以,要计算1!到10!的和,我们可以逐个计算每个数的阶乘然后相加。下面是具体计算过程:

Markdown
1! = 1
2! = 2 * 1 = 2
3! = 3 * 2 * 1 = 6
4! = 4 * 3 * 2 * 1 = 24
5! = 5 * 4 * 3 * 2 * 1 = 120
6! = 6 * 5 * 4 * 3 * 2 * 1 = 720
7! = 7 * 6 * 5 * 4 * 3 * 2 * 1 = 5040
8! = 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 40320
9! = 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 362880
10! = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 3628800
求和:
1! + 2! + 3! + 4! + ... + 9! + 10!
= 1 + 2 + 6 + 24 + 120 + 720 + 5040 + 40320 + 362880 + 3628800

将上述阶乘值相加得到最终结果。由于这是一个手动计算的过程,我这里直接给出计算器的结果:

1! + 2! + 3! + 4! + ... + 9! + 10! = 5,006,550

请看下⾯的代码:

#include <stdio.h>
//写⼀个代码求n的阶乘
int main()
{int n = 0;scanf("%d", &n);int i = 1;int ret = 1;for(i=1; i<=n; i++){ret=ret*i;}
return 0;
}

特例代码和内存

在这里插入图片描述

  1. 栈区内存的使⽤习惯是从⾼地址向 低地址使⽤的,所以变量i的地址是 较⼤的。arr数组的地址整体是⼩ 于i的地址。
  2. 数组在内存中的存放是:随着下标 的增⻓,地址是由低到⾼变化的。 所以根据代码,就能理解为什么是左 边的代码布局了。 如果是左边的内存布局,那随着数组 下标的增⻓,往后越界就有可能覆盖 到i,这样就可能造成死循环的。为什么i和arr
    数组之间恰好空出来2个整型的空间 呢?这⾥确实是巧合,在不同的编译 器下可能中间的空出的空间⼤⼩是不 ⼀样的,代码中这些变量内存的分配
    和地址分配是编译器指定的,所以的 不同的编译器之间就有差异了。所以 这个题⽬是和环境相关的。

从这个理解我们能够体会到调试的重要性,只有调试才能观察到程序内部执⾏的细节,就像医⽣给病 ⼈做B超,CT⼀样。在这片充满狂野西部风情的C语言编程疆域,我们摇身一变成为Visual Studio(VS)编译舞台上的牛仔程序员,骑着代码骏马,在栈区、堆区和静态存储区这三大内存荒原上演绎了一场别具一格、笑料百出的捉虫大戏。这些如同草原上狡猾狐狸的小bug们,总是在不经意间躲进内存区域的沟壑之间,却不知我们的牛仔眼明手快,正握紧VS编译器这把熠熠生辉的六发左轮,准备在内存的广袤天地中来一场酣畅淋漓的追逐赛。

我们在栈区狭长的峡谷里与递归bug斗智斗勇,犹如牛仔在曲折蜿蜒的山道上追踪狡猾的羚羊;在堆区那片辽阔无垠的草原上,面对动态分配带来的迷雾重重,我们化身成精准定位的猎人,一次次击中那些藏匿其中的bug群落;而在静态区永恒不变的石漠之中,我们探寻全局变量的神秘踪迹,展现出了牛仔般的坚韧与耐心。

未来的编程拓荒之路上,让我们戴上牛仔帽,腰挎VS编译器这把威力无比的“Bug终结者”,在栈、堆、静态区的三重奏中翩翩起舞,演绎更多令人捧腹又不失智慧的“牛仔捉虫记”。不论是遭遇坎坷还是收获荣耀,每个在VS编译舞台上挥洒汗水的“内存牛仔”都将化身为英勇且诙谐的英雄,用他们的奇思妙想和过硬技能,为这片编程世界的内存荒原带来欢笑与和谐!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/627583.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【小黑嵌入式系统第十五课】μC/OS-III程序设计基础(四)——消息队列(工作方式数据通信生产者消费者模型)、动态内存管理、定时器管理

上一课&#xff1a; 【小黑嵌入式系统第十四课】μC/OS-III程序设计基础&#xff08;三&#xff09;——信号量&#xff08;任务同步&资源同步&#xff09;、事件标记组&#xff08;与&或&多个任务&#xff09; 前些天发现了一个巨牛的人工智能学习网站&#xff0c…

Blazor 根据路由判断哪些页面需要加模板,哪些不需要

比如我们的登录的页面是不需要加通用模板的&#xff0c;通过if 控制 RouteView的DefaultLayout即可 <BootstrapBlazorRoot><Router AppAssembly"typeof(App).Assembly"><Found Context"routeData"><PageTitle>Title</PageTitl…

【备战蓝桥杯】如何使用Python 内置模块datetime去计算我与CSDN相遇的天数

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-6gfBeOb6YRf7C52d {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

倒计时1天|解锁「PolarDB开发者大会」正确打开方式

1月17日 9:30-16:30 北京嘉瑞文化中心 PolarDB开发者大会 明天就要和大家就见面啦&#xff5e; 大会参会指南现已出炉 各位开发者们&#xff0c;请查收~ &#x1f447;&#x1f447;&#x1f447; 点击 大会主页 or 扫描上方二维码 一键抵达大会官网&#x1f447; 查看…

Java方法及方法重载的详解

目录 一、方法的概念及使用 1.1 方法的概念 1.2 方法的定义 1.3 方法调用的执行过程 1.4 实参和形参的关系 1.5 没有返回值的方法 二、方法的重载 2.1 方法重载存在的原因 2.2 方法重载的概念 一、方法的概念及使用 1.1 方法的概念 方法就是一个代码片段. 类似于 C …

服务优雅停机SpringBoot

什么是优雅停机 ​ 优雅停机指的是Java项目在停机时需要做好断后工作。如果直接使用kill -9 方式暴力的将项目停掉&#xff0c;可能会导致正常处理的请求、定时任务、RMI、注销注册中心等出现数据不一致问题。 ​ 如何解决优雅停机呢&#xff1f;大致需要解决如下问题&#xf…

【Linux】 RPM 命令参数使用

rpm 执行安装包二进制包&#xff08;Binary&#xff09;以及源代码包&#xff08;Source&#xff09;两种。二进制包可以直接安装在计算机中&#xff0c;而源代码包将会由 RPM自动编译、安装。源代码包经常以src.rpm作为后缀名。 常用命令组合&#xff1a; &#xff0d;ivh&a…

GZ075 云计算应用赛题第8套

2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷8 某企业根据自身业务需求&#xff0c;实施数字化转型&#xff0c;规划和建设数字化平台&#xff0c;平台聚焦“DevOps开发运维一体化”和“数据驱动产品开发”&#xff0c;拟采用开源OpenSt…

x-cmd pkg | tokei - 代码行数统计工具

目录 简介首次用户技术特点竞品和相关作品进一步阅读 简介 tokei 是一个使用 Rust 编写的显示有关代码统计信息的命令行工具&#xff0c;可以分门别类的统计目录内的代码行数。 tokei 具有良好的跨平台性&#xff0c;可以在 Linux、macOS、Windows 等多种平台上安装运行。 首…

林江院长:让斜视的孩子改“斜”归正,“正视”未来

读写时跳行、不敢和别人对视、拍照时不敢看镜头......这些不便是不少斜视患儿每天都在经历的日常。 斜视是目前儿童常见的眼科疾病之一&#xff0c;该眼病不仅给孩子的外在形象带来影响&#xff0c;更重要的是会影响双眼视功能及身心健康&#xff0c;其危害不容小觑。 7岁男孩晓…

程序员晋升管理者后的自我修养

谈到技术管理&#xff0c;首要的一点就是管理者的角色认知问题&#xff0c;因此本篇文章的主要内容就是如何增强管理者的角色认知&#xff0c;持续提升自我管理能力。 作为管理者&#xff0c;首要任务就是要认清自我并管理好自己&#xff0c;要树立对管理者角色的正确认知&…

【线路图】 DC-DC升压恒压控制驱动芯片 2.8-40V AP8100

说明 AP8100 是一款外围电路简单的 BOOST 升压恒压控 制驱动芯片&#xff0c;适用于 2.8-40V 输入电压范围的升压恒 压电源应用领域&#xff0c;启动电压可以低至 2.5V 。 芯片会根据负载的大小自动切换 PWM &#xff0c; PFM 和 BURST 模式以提高各个负载端的…

AI魔幻巨制电影《权力的游戏:重生之战》

AI魔幻巨制电影《权力的游戏&#xff1a;重生之战》 《冰与火之歌》龙妈雪诺后裔是谁&#xff1f;你相信龙族的力量可以改变维斯特洛大陆的命运吗&#xff1f; 在《权力的游戏&#xff1a;重生之战》中&#xff0c;维斯特洛大陆再次陷入混乱之中&#xff0c;但这一次的混乱并非…

Redis 交互模式

交互模式&#xff08;Interact Mode&#xff09; 安装 Redis 时通常连带安装了一个 Redis CLI &#xff08;apt install redis 或者是 apt install redis-cli 类似的&#xff09;。在本博客中将会对 redis-cli 中的常用命令做一个使用介绍&#xff0c;下文中以黑色代码块表示在…

Python单元测试框架:pytest常用测试报告类型

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 先前博客有介绍pytest测试框架的安装及使用&#xff0c;现在来聊…

Linux用户提权

新建用户 用root账户修改文件&#xff0c;添加信任用户 使用sudo提权&#xff0c;可以使用 **root删除新建账户**

JavaScript:JQuery.Ajax之错误调试帮助信息

JQuery.Ajax之错误调试帮助信息 代码&#xff1a; $(document).ready(function() {$("#info").click(function() {$.ajax({url: "/v1/getInfo",type: "post",data: { id: 1 },dataType: "json",success: function(msg) {alert(msg);}…

联想小新M7268一体机常用功能和操作步骤

联想小新M7268黑白激光多功能打印一体机&#xff0c;小身材、大智慧&#xff0c;小心M7268身材十分娇小&#xff0c;净尺寸方面为350*275*135mm&#xff08;长*宽*高&#xff09;&#xff08;手工测量&#xff09;&#xff0c;在实际使用时&#xff0c;小新M7268所占空间要略大…

js find方法的使用

JavaScript中的数组find()方法用于查找满足指定条件的第一个数组元素&#xff0c;并返回该元素。 find()方法的语法如下&#xff1a; array.find(callback[, thisArg]) 其中&#xff0c;array是要进行查找的数组&#xff0c;callback是一个回调函数&#xff0c;用于定义查找…

【笔记】认识电机

认识电机 电机一些概念永磁同步电机永磁体定子和转子励磁电磁感应定律 AC Optimal Power Flow功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右Smart…