通常来说,在 C 文件 底部是否留空行,理论上不应该直接导致单片机卡死。 C 语言标准以及大多数编译器(包括针对单片机的编译器)都不会强制要求 C 源文件必须以空行结尾。
在嵌入式开发的世界里,我们经常会遇到各种奇奇怪怪的问题。最近,我就碰到了一个让人哭笑不得的 “灵异” 事件:仅仅因为一个 C 代码文件 底部没有留空行,我的单片机程序竟然直接 卡死 了! 你没听错,就是这么匪夷所思,听起来像是天方夜谭,但它确实发生了。 这篇文章就来聊聊这次令人费解的 bug 经历,以及我是如何抽丝剥茧,最终找到(可能是)真相的。
最近在 Keil MDK 环境下开发一个基于 [stc32g] 的项目,一切进展顺利。然而,在进行某一模块的代码修改后,我发现程序突然变得不稳定起来。具体表现为:
-
程序烧录到单片机后,运行一段时间就 完全失去响应,就像“卡死”了一样。
-
串口 没有输出任何信息 (如果有串口调试信息的话)。
-
硬件指示灯 停止闪烁 (如果有指示程序运行状态的指示灯)。
-
复位单片机后,程序可以重新“运行”,但很快又会再次卡死。
起初,我以为是新修改的代码逻辑存在严重错误,导致程序跑飞。于是,我开始了漫长的代码审查、调试之旅。各种 printf 调试大法、单步调试、内存检查轮番上阵,但始终找不到明显的代码逻辑错误。 更让人崩溃的是,问题 时而出现,时而消失,非常玄学。
“罪魁祸首” 竟然是……文件末尾的空行?
就在我快要放弃的时候,一次偶然的操作让我发现了问题的 “真相”。 我习惯在每次修改代码后,都 手动在文件末尾添加一个空行 (这只是个人习惯,并非强制要求)。 当我再次修改并保存某个 C 源文件后,奇迹发生了: 程序竟然恢复正常了! 为了验证是否是空行的作用,我又尝试 删除文件末尾的空行,重新编译烧录,结果 单片机再次卡死!
这简直是滑天下之大稽!