本文经AI新媒体量子位(公众号ID:QbitAI)授权转载,转载请联系出处。最简单的helloworld,居然也有bug?不是这段代码还能写错,而是在运行时发现了操作系统异常处理的很多漏洞。当结果输出到/dev/full,即设备空间不足,任何写入都应该失败时,C语言仍然返回0,成功退出:$gcchello.c-ohello$./hello>/dev/full$echo$?0该错误的最初发现者说:这不是一个小错误,本质上是一个“打印到标准输出”的任务。发生错误但没有抛出异常,这意味着即使数据丢失,进程也会继续运行。于是他坚持做下去,测试了C++、Python、Java等流行语言,发了博客,很快就在论坛上盖了一座高楼,讨论度顿时炸了:while评论区网友议论纷纷Debug,综合梳理下来,踩过这个bug的语言多达16种!HelloWorld的Debug进程的最初发现者是一位技术博主,名叫sunfishcode。在他的博客中,他展示了C和Python的详细调试过程。它主要使用Linux系统下一个经典的设备文件,/dev/full。/dev/full在写入时总是返回设备上没有剩余空间(错误码为ENOSPC),常用于测试程序是否能正确处理I/O错误。如果程序正常,则返回错误报告:$echo"HelloWorld!">/dev/fullbash:echo:writeerror:Nospaceleftondevice$echo$?1而正如我们一开始展示的代码,使用C语言输出时,hello程序报告成功并返回0。使用strace命令跟踪这个进程产生的系统调用,可以发现程序确实失败了:$strace-etrace=write./hello>/dev/fullwrite(1,"HelloWorld!\n",13)=-1ENOSPC(Nospaceleftondevice)+++exitedwith0+++还有标语“Errorsshouldnotbepassedquietly”的Python,也提出了一个观点。程序向stderr打印了一条消息,丢失了信息,但最后也返回了0:$python2hello.py>/dev/fullclosefailedinfileobjectdestructor:sys.excepthookismissingsys.stderr$echo$?0这个bug严重吗?现实世界中没有一个程序会把HelloWorld当作一个关键的安全问题,但是“打印到标准输出”是一个现实中确实存在的程序任务。这就是最简单的程序HelloWorld的本质。博主sunfishcode是这样说的:标准输出可能是指某个特定的文件,那么如果文件空间刚好用完,程序因为bug没有检测到这个错误怎么办?父进程不会知道子进程失败了,它会继续运行。但是预期生成的输出实际上丢失了数据。当然,博主最后还给出了一个没有踩雷的语言列表:网友热议:这是bug吗?目前博主已经针对这个bug给出了一些解决方案。例如在C语言环境下,可以使用这种方法:#include
