「Hello World」中的「bug」

2022 年 3 月 22 日 机器之心

选自sunfishcode博客

作者:sunfishcode
机器之心编译
机器之心编辑部
Hello World 可能是许多人编写的第一个程序。这么简单的程序按理说应该没有 bug 吧?一位叫「sunfishcode」的开发者给出了令人意外的结论。


C 语言中的 Hello World

用 C 语言写 Hello World 有很多种不同的方式,比如维基百科里记录的版本、K&R book 中介绍的版本,甚至还有 1974 年的原始版本。


这里展示一个 ANSI C 的版本:

/* Hello World in C, Ansi-style */#include <stdio.h>#include <stdlib.h>int main(void){      puts("Hello World!");      return EXIT_SUCCESS;}

这个版本使用 (void) 来确保 main 是一个新型的声明。它使用 EXIT_SUCCESS 宏,而不是假设平台使用 0 表示 success,根据 C 的标准,这是不必要的。但我们在这里不会冒任何风险。它使用适当的头文件以避免隐式声明 puts。

这个版本试图把每件事都做好,但它仍然有一个缺陷。

上面提到的所有版本都有一个 bug。

bug 在哪儿?

Linux 有一个有趣的设备文件,叫做「/dev/full」,就像它更著名的表亲「/dev/null」一样。但是当你写入「/dev/full」时,它不会丢弃数据,而是会失败。它的作用就像文件系统中一个刚刚耗尽空间的文件:

$ echo "Hello World!" > /dev/fullbash: echo: write error: No space left on device$ echo $?1

这是一个很好的小工具,用于测试程序能否正确处理 I/O 错误。如果没有剩余的空间,或者磁盘出现故障,那么创建实际的文件系统是很不方便的,但是让一个程序将其输出写入「/dev/full」,然后看看会发生什么,这是非常容易的。

让我们测试一下上面的 C 语言例子:

$ gcc hello.c -o hello$ ./hello > /dev/full$ echo $?0

与在上面的 shell 中使用 echo 不同,这里没有输出,退出状态为零。这意味着 hello 程序报告了成功执行。然而,它实际上并没有成功。我们可以通过使用 strace 确认它遇到了故障。

$ strace -etrace=write ./hello > /dev/fullwrite(1, "Hello World!\n", 13)          = -1 ENOSPC (No space left on device)+++ exited with 0 +++

操作系统报告了「No space」错误,但没关系,程序默默地接受它并返回 0,这是成功的代码。这是一个 bug!

这个 bug 有多严重?可以说,hello world 在任何地方都不会是安全的。然而,hello world 确实做了一些现实世界的程序所做的事情:打印到标准输出,这可能会被重定向到一个文件。在现实世界中,文件可能会耗尽空间。如果一个程序没有检测到这种错误并通过其返回代码报告该错误,那么它的父进程将不知道子进程失败了,并且将继续运行,就像没有任何错误一样,即使它期望产生的输出已经悄悄地丢失了数据。

例如,考虑一个将 yaml 文件打印到标准输出的程序。如果标准输出耗尽空间,则输出可能会在某个任意点被截断,尽管它可能仍然是有效的 yaml。因此,我们应该期待程序能够检测和报告这种情况。

如果换成其他语言呢?

在前面的内容中,我们重点看了 bash 和 C,那如果换成 Python 呢?Python 处理错误的原则可是「Errors should never pass silently」。以下是 Python 2 的情况:

$ python2 hello.py > /dev/fullclose failed in file object destructor:sys.excepthook is missinglost sys.stderr$ echo $?0

它确实向 stderr 打印了一条消息,尽管这是一条令人困惑的消息。但是,它也返回 0,这意味着它告诉运行它的人它已经成功退出。

幸运的是,Python 3 正确地报告了错误,并打印了一个更好的错误消息:

$ python3 hello.py > /dev/fullException ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>OSError: [Errno 28] No space left on device$ echo $?120

最后,作者又尝试了几种语言,结果如下:



原文链接:https://blog.sunfishcode.online/bugs-in-hello-world/
封面出自:https://lmichelin.fr/hello-world/


© THE END 

转载请联系本公众号获得授权

投稿或寻求报道:content@jiqizhixin.com

登录查看更多
0

相关内容

程序猿的天敌 有时是一个不能碰的magic
【干货书】C++实战编程指南,附549页pdf与Slides
专知会员服务
80+阅读 · 2021年4月23日
专知会员服务
141+阅读 · 2020年12月28日
【2020新书】C语言编程傻瓜式入门,第二版,464页pdf
专知会员服务
60+阅读 · 2020年10月15日
【实用书】Python编程,140页pdf
专知会员服务
41+阅读 · 2020年8月20日
流畅的Python 中英文版 PDF 高清电子书
专知会员服务
80+阅读 · 2020年8月2日
“C 不再是一种编程语言!”
CSDN
0+阅读 · 2022年4月4日
“C不再是一种编程语言”
AI前线
1+阅读 · 2022年4月2日
2021 年 Python 的好与坏
InfoQ
2+阅读 · 2021年11月16日
我用Transformer修复代码bug
夕小瑶的卖萌屋
1+阅读 · 2021年9月9日
国家自然科学基金
0+阅读 · 2015年12月31日
国家自然科学基金
0+阅读 · 2014年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2011年12月31日
国家自然科学基金
0+阅读 · 2011年12月31日
国家自然科学基金
0+阅读 · 2008年12月31日
国家自然科学基金
1+阅读 · 2008年12月31日
Building Odia Shallow Parser
Arxiv
0+阅读 · 2022年4月19日
Arxiv
0+阅读 · 2022年4月18日
Arxiv
13+阅读 · 2021年3月29日
VIP会员
相关VIP内容
相关基金
国家自然科学基金
0+阅读 · 2015年12月31日
国家自然科学基金
0+阅读 · 2014年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2013年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2012年12月31日
国家自然科学基金
0+阅读 · 2011年12月31日
国家自然科学基金
0+阅读 · 2011年12月31日
国家自然科学基金
0+阅读 · 2008年12月31日
国家自然科学基金
1+阅读 · 2008年12月31日
Top
微信扫码咨询专知VIP会员