一个古怪的bug调试过程

新手程序员怎么修改bug?贯穿debug的经验,送给你们~ 修改bug入手,通过一个个小bug去了解整个project的结构和design pattern,对新人来说,这种学习既直观又不会被复杂的代码吓死。 几个debug的经验: 1. 优先解决那些可重现的,可重现的bug特别好找,反复调试测试就好了,先把好解决的干掉,这样最节约时间。 2. 对于某些bug没有头绪或者现象古怪不知道从哪里下手,找有经验的同事问一下思路,因为在那种开发多年的大型系统里,经常会反复出现同样原因的bug, 原因都类似,改了一处,过一阵子另外一处又冒出来,而且无法根治。 比如 阅读详情
也许这也不能算是一个bug,只不过没有了解清楚一个函数的确切用法罢了。这一切都源于一个经典的程序:

#include <stdio.h>
#include <ctype.h>


int main(void)
{
char intput,upper;
while((input=getchar())!=EOF)
{
upper=toupper(input);
putchar(upper);
}
return 0;
}


当我输入abcd'\n'的时候,输出是ABCD'\n',这很正常;
当我输入ctrl+D(也就是EOF),结束程序,这也很正常;
但是,如果我输入abcd'EOF'呢?结果会在当前行输出ABCD,按照道理,程序读取到EOF是会结束的吗?这到底发生什么事了?
如果没有强大的调试工具GDB的帮助下,也许这就一直是我一个小小的困惑,但是GDB太好用了,所以我发现了问题的所在。
让我先GDB一下吧:
先把断点设置子line 8:break 8
接着run,display input和upper,你会发现这两个字符是会有初始值的:
1: input = 0 '\000'
2: upper = 40 '('
然后,step,程序会进行while语句,由于input!=EOF,所以会进行getchar函数,这时候可以输入字符,我输入
ab'EOF'
神奇的事情发生了,当我输入EOF之后,程序立马退出getchar函数,来到下一语句:


(gdb) s
ab10 upper=toupper(input);
2: upper = 40 '('
1: input = 97 'a' 我们可以看到这时候input已经接收了第一个字符a


我们接着s:


(gdb) s
11 putchar(upper);
2: upper = 65 'A' 执行过toupper函数之后,upper等于字符A
1: input = 97 'a'


接着s,我发现这时候字符A并没有输出,而是直接跳至while循环:
(gdb) s
8 while((input=getchar())!=EOF)
2: upper = 65 'A'
1: input = 97 'a'
接着s,跟之前类似:
(gdb) s
10 upper=toupper(input);
2: upper = 65 'A'
1: input = 98 'b'
接着s,还是跟之前类似:


(gdb) s
11 putchar(upper);
2: upper = 66 'B'
1: input = 98 'b'
接着s,又跳至while循环,putchar还是没有输出:


(gdb) s
8 while((input=getchar())!=EOF)
2: upper = 66 'B'
1: input = 98 'b'


我们再接再厉,s一下:
这时候很神奇的是:终于有输出了,是在输入当前行输出AB。
当我们直接输入EOF的时候,getchar马上接收到EOF信号退出函数。


我再来一个正常的例子来实验一下,输入为:ad'\n',结果发现
程序运行到最后一个字符回车符的时候,就已经可以输出了:
(gdb) s
11 putchar(upper);
2: upper = 10 '\n'
1: input = 10 '\n'


(gdb) s
AD 跳至while循环的时候已经有输出了
8 while((input=getchar())!=EOF)
2: upper = 10 '\n'
1: input = 10 '\n'


我把上面的情况总结一下:


(1)getchar只认得第一个输入的EOF,如果前面有多个字符后面接着一个EOF,则EOF只会让getchar函数结束,getchar不会接收EOF,只接收前面输入的字符;
(2)putchar不是马上输出字符,而是一个一个输出,如果遇到回车,则输出所有字符,但是如果是多个字符加一个EOF,情况就发生改变,运行完putchar并不马上输出,而是要运行至getchar函数后才输出。


这实在是一个难以解释的bug。


不过,我猜测是这样的:
getchar函数和putchar函数共同维护着同一个缓冲区,getchar函数在运行之前会将缓冲区内部的所有数据清空并输出,由于刚开始的时候缓冲区都是'\0',所以什么也没有显示,我只能看到getchar正准备接收字符。putchar函数则会再遇到'\n' 的时候将缓冲区数据输出,由于我们是多个字符后面接着EOF,且EOF没有被getchar读取,所以putchar再运行至最后一个字符时仍然不输出。直到再次运行getchar函数,它将缓冲区所有的字符输出,所以我们看到输出了。getchar只能认识第一次就输入的EOF,否则会让其退出。


这便是我的猜测了,如果能看到源代码,那问题就好办多了。













哨兵2号遥感影像解析全流程:步骤、算法与AI应用详解 未来,多源数据融合与边缘计算技术的应用将进一步拓展遥感解析的边界。波段合成:选择10m分辨率波段(如B2、B3、B4、B8)进行Layer Stacking,生成多光谱影像。| 分类与识别 | Scikit-Learn、PyTorch | SVM、CNN、K-Means聚类 | 地块分类、目标检测 || 数据预处理 | SNAP、Sen2Cor | 大气校正、几何校正 | L2A产品生成、格式转换 || 波段融合 | ENVI、GDAL | Layer Stacking、重采样 | 多光谱影像合成 | 阅读详情

相关推荐

N32在Keil中J-Link识别失败的排查与修复指南

本文详细解析了在Keil开发环境中,J-Link调试器无法识别N32系列MCU的常见问题。通过分步指导,从检查修改Keil工程配置文件、更新J-Link驱动,到手动添加N32专用设备支持包,系统性地提供了排查与修复方案,帮助开发者快速恢复调试连接,确保开发流程顺畅。

301

记一次Blog迁移到Ghost(内含干货)

欢迎来互换友链:记一次Blog迁移到Ghost 记一次Blog迁移到Ghost 之前的用了Hexo搭建了Blog,不过由于某次的操作失误导致Hexo本地的source源文件全部丢失.留下的只有网页的Html文件,众所周知,Hexo是一个本地编译部署类型的Blog系统,个人感觉这种类型的Blog特别不稳定,如果本地出了一些问题那么线上就GG了,当然,使用git是可以管理源文件,但是源文件里又包含很多...

weixin_34392906的博客 972

反激变压器反射电压详解

我以前做过隔离式的POE模块,其电路实际就是个反激式开关电源。只不过其输入电压范围比较低,为44V-57V。 电路如下图,就是个flyback。 可以看到,电路中有个钳位电路,用来抑制电压尖峰,就在初级线圈那里。 问题 抑制尖峰通常有2种电路,一种叫RCD钳位,另外一种是用TVS管+二极管钳位。 这两种实际中都有用,今天我不想讨论它们的区别,只想说明一个问题: 为什么不能只用一个二极管搞定?像继电器电路那样?不也能抑制尖峰吗? 答案自然是不行的...

weixin_42005993的博客 2万+

BUG收集

这篇文章用来记录学习过程中遇到的BUG以及相应的解决方式 日期#

ghost41998的博客 293

手把手教你配置UEFI Secure Boot:从密钥生成到系统验证(附避坑指南)

本文详细介绍了如何配置UEFI Secure Boot,从密钥生成到系统验证的全过程,包括PK、KEK等关键密钥的生成方法,以及常见问题的解决方案。通过实战案例和避坑指南,帮助用户有效提升系统启动安全性,防止恶意软件植入。

weixin_30776273的博客 340

基于深度学习的水果新鲜程度检测系统(UI界面 + YOLOv8/v7/v6/v5代码 + 训练数据集)

本文详细介绍了如何使用YOLO系列模型(YOLOv5、YOLOv6、YOLOv7、YOLOv8)构建水果新鲜度检测系统。通过数据集准备、模型训练、推理过程以及UI界面的实现,我们能够构建一个实时检测水果新鲜度的系统。通过本博客,您可以全面了解如何应用深度学习技术解决实际问题,尤其是在智能监控和食品质量检测领域。

YOLO 815

手把手教你搭建一个属于自己的Ghost博客

介绍Ghost 是基于 Node.js 的开源博客平台,由前 WordPress UI 部门主管 John O’Nolan 和 WordPress 高级工程师(女) Hannah Wolfe 创立,目的是为了给用户提供一种更加纯粹的内容写作与发布平台。环境 腾讯云CVM CentOS 6.5_x64(纯净版) Node v0.10.40(官方建议版本) Nginx 1.80 Mysql 5.1.73

无悔铭 1万+

人工智能算法面试大总结-总目录

涉及秋招、春招、社招

啥都生的博客 2万+

关于变量定义的古怪bug

今天调试了一份以前写的code,用的C。问题相当之古怪,最后的结果也令人惊讶。简单来说,两个部分,一个文件解析,一个具体动作。文件解析把结果打包交给动作部分执行。从功能上讲,文件解析出来的内容对于动作模块是黑盒,也就是无论解析出来的内容是什么,对还是错,对于动作模块是没有影响的。校验适量一个部分做的。但是这里出现了问题,当解析部分添加了一个option内容后,在某些情况下动作模块无法运行了。在排除...

藏漏屋 159

MATLAB算法实战应用案例精讲-【数模应用】装箱问题

装箱问题可以根据不同的维度进行分类。以下是一些常见的装箱问题二维装箱问题:二维装箱问题假设所有物品都是平面上的矩形,并且需要将它们放入平面上的容器中。这个问题的目标是找到一种装箱方案,使得物品不重叠并占据的总面积最小。三维装箱问题:三维装箱问题考虑到物品可以具有高度,并且需要将它们放入三维容器(如箱子或货柜)中。目标是找到一种装箱方案,使得物品不重叠且总体积最小。多维装箱问题:多维装箱问题是指在更高维度空间中进行装箱的问题。除了长度和宽度之外,物品可能具有其他属性,如高度、重量、形状等。

qq_36130719的博客 1572

UFAST车道线检测 Ultra-Fast-Lane-Detection 从环境搭建到复现完成(一)

UFAST车道线检测 Ultra-Fast-Lane-Detection 从环境搭建到复现完成(一)

m0_46364958的博客 4345

小黄鸭调试法:拯救那些开发心里“无力回天”的bug

当我们遇到一个Bug或疑难问题被卡住,迟迟没有解决思路,最后都要脑袋炸掉的时候,有的人就放弃不搞了,然后就摔门出去逛大街了,或者有时随便拉个人过来,和他 blablabla 讲一通。当你向这只始终保持沉默的鸭子解释代码的过程中,你会发现你的想法、观点、或思路,可能和实际的代码发生了偏离,于是你就可能突然就找到了代码中bug产生的原因了,从而想出解决办法;然后把这个玩偶鸭子放在你的面前,标准做法是放在你的桌子上,电脑显示器旁边,或是键盘边,反正是你的跟前,面朝着你;上面说的步骤去做,神功即可大成!

威哥爱编程,华为 HDE,鸿蒙极客、优快云博客专家、《鸿蒙 HarmonyOS 5/6 开发之路》系列图书第一作者 1574

EtherCAT主站SOEM -- 19 --Qt-Soem通过CSP模式(周期同步位置模式)控制一个电机转圈圈

以上就是EtherCAT主站SOEM – 19 --Qt-Soem通过CSP模式(周期同步位置模式)控制一个电机转圈圈的内容。有不明白的地方欢迎留言;有建议欢迎留言,我后面编写文档好改进。创作不容,如果文档对您有帮助,记得给个赞。

常驻客栈的博客--嵌入式EtherCAT 1996

程序员界改BUG“神”发明,学会10分钟搞定一个BUG

对于大部分开发人员来说,你所看到的绝大部分BUG已经被别人修复并且分享出来了,这时候百度已经足以帮你 但是你也有可能会遇到一些稀奇古怪的Bug,这时候你就需要静下心来,好好的仔细研究一下了。下面,分享一下我偶然得到的心得体会。 首先,找出Bug 换环境 换用户 换数据 换浏览器 换版本 换种操作 找到Bug之后,再搞清楚下面这几个问题...

java03_15的博客 1779

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

如何调试bug

程序员的大多数时候,总是在debug的,因为程序不可能写出来的时候就是完好的。而代码质量很大取决于程序员的质量,如果你碰到了,那还能咱办呢,低头DEBUG吧。    以下是我在网上找的一些debug技巧。      1. 优先解决那些可重现的,可重现的bug特别好找,反复调试测试就好了,先把好解决的干掉,这样最节约时间。  2. 对于某些bug没有头绪或者现象古怪不知道从哪里下手,找有经验的同

u011347756的专栏 727

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

开发必备神器,可让初级程序员十分钟解决一个BUG

对于大部分开发人员来说,你所看到的绝大部分BUG已经被别人修复并且分享出来了,这时候百度已经足以帮你 但是你也有可能会遇到一些稀奇古怪的Bug,这时候你就需要静下心来,好好的仔细研究一下了。下面,分享一下我偶然得到的心得体会。 首先,找出Bug 换环境 换用户 换数据 换浏览器 换版本 换种操作 找到Bug之后,再搞清楚下面这几个...

taya_a的博客 844

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

程序员怎么找BUG

二分法可以帮助我们快速缩小问题的范围,从而精确定位到问题代码。通过先确定出现问题代码范围,然后通过注释代码方式,看看还会不会出问题,类似二分查找的方法,逐步缩小问题范围。对于某些bug没有头绪或者现象古怪不知道从哪里下手,找有经验的前辈问一下思路,因为前辈之所以能成为前辈,也都是一个坑一个坑的踩过来,我们碰到的问题,人家说不定都碰到过。通过在代码里面添加断点,能够让我们对代码逻辑,执行顺序,以及各种中间结果更加清晰,更容易定位出BUG产生的原因。

caisexi的博客 406

新人程序员如何在复杂的程序中寻找Bug?

很多新人程序员敲代码的经验几乎为零,更别提准确的找到Bug了。那么如何寻找Bug呢?修复Bug不容易,找到方法或许可以事半功倍哦! 1、优先解决那些可重现的bug 可重现的bug特别好找,反复调试测试就好了,先把好解决的干掉,这样最节约时间。 2、与有经验的同事分享思路 对于某些bug...

chiluoyan2037的博客 553

如何快速查找BUG?

对于程序员而言,有一样东西是绝对不想碰见却又一定会遇到的,那就是Bug。 鲁迅曾经说过,当我们遇见Bug时要冷静,不要慌。 好吧,鲁迅并没说过这句话。开发应用程序是一个非常有压力的工作,没有人是完美的,因此在这个行业中,代码中出现bug是相当普遍的现象。 一个bug并不可怕 可怕的是发现一个bug,修改之后,会出现一群Bug,此时,我相信你的内心是崩溃的...

Tys53628的博客 1万+

程序员是如何从复杂的代码里找到 bug 的?

我曾经做了两年大型软件的维护工作,那个项目有 10 多年了,大约 3000 万行以上的代码,参与过开发的有数千人,代码 checkout 出来有大约 5 个 GB,而且 bug 特别多,open 的有上千,即使最高优先级的 showstopper 也有上百。分享下我的 debug 的经验。 1. 优先解决那些可重现的 可重现的 bug 特别好找,反复调试测试就好了,先把好解决的干掉...

生命在于折腾 1436

程序员如何去快速定位bug

找 bug(如 Testing)与去 bug(Debugging),这在软件工程里是两个截然不同的任务。发现 bugs,测试并非唯一手段,其他还有 Code Review、Inspection 等等。 找 bugs 通常有几个相对快速的办法。 比如,为 code base 编写/添加更多的自动单元测试,这是一种白盒测试。你 Mentor 让你“先从找 code base 中 bug 开始”,除了让...

qq_45557294的博客 631

程序员新人怎样在复杂代码中找bug

via: http://wmcxy.iteye.com/blog/2153249   1. 优先解决那些可重现的,可重现的bug特别好找,反复调试测试就好了,先把好解决的干掉,这样最节约时间。   2. 对于某些bug没有头绪或者现象古怪不知道从哪里下手,找有经验的同事问一下思路,因为在那种开发多年的大型系统里,经常会反复出现同样原因的bug,原因都类似,改了一处,过一阵子另外一处又冒出来

mikyz的专栏 429

查找程序的bug

分享debug经验 1. 优先解决那些可重现的,可重现的bug特别好找,反复调试测试就好了,先把好解决的干掉,这样最节约时间。 2. 对于某些bug没有头绪或者现象古怪不知道从哪里下手,找有经验的同事问一下思路,因为在那种开发多年的大型系统里,经常会反复出现同样原因的bug,原因都类似,改了一处,过一阵子另外一处又冒出来,而且无法根治。 比如:我那个系统里有个特别危险的API,接口参

simon106的博客 471

android开发如何快速定位bug_程序员如何去快速定位bug

找 bug(如 Testing)与去 bug(Debugging),这在软件工程里是两个截然不同的任务。发现 bugs,测试并非唯一手段,其他还有 Code Review、Inspection 等等。找 bugs 通常有几个相对快速的办法。比如,为 code base 编写/添加更多的自动单元测试,这是一种白盒测试。你 Mentor 让你“先从找 code base 中 bug 开始”,除了让新手...

weixin_39638014的博客 284

火眼金睛:调试——关于软件开发你需要知道些什么

1、作为一名软件开发者,你将花大量的时间用于调试代码。既然你的大部分时间都花在调试代码上了,那么擅长调试可是一门好手艺,你不这样认为吗? 2、知道如何写出优质代码是一回事,知道如何调试你这一辈子所能见到的最丑陋的代码是另一回事。 3、本文中,将介绍一种系统化的调试方法,这将帮助你有效规避那种可怕的“调试器心态”,并将你的调试技能提升到更高的水平。

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 916

程序员如何在复杂代码中查找到程序的bug?

最近在挑选更合适的物品来兑换,请牛牛们不要着急。 程序员新人怎样在复杂代码中找 bug? 姚冬,程序员: 我曾经做了两年大型软件的维护工作,那个项目有10多年了,大约3000万行以上的代码,参与过开发的有数千人,代码checkout出来有大约5个GB,而且bug特别多,open的有上千,即使最高优先级的showstopper也有上百。 分享下我的debug的经验 1.

走向架构师之路 3987
上一篇: 技术规划
下一篇: C语言堆栈入门——堆和栈的区别( 转自http://www.top-e.org/)
GhostComputing
博客等级 码龄16年 6粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值