Hello World程序里居然有bug!
Posted turingbooks
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hello World程序里居然有bug!相关的知识,希望对你有一定的参考价值。
Hello World可能是码农们最常写的计算机程序了。很多人在刚开始学习一种新的编程语言时,编写的第一个程序就是Hello World。
所以这个看上去毫无特别之处的入门程序,真的一点儿bug也没有吗?
毕竟Hello World程序只做一件事,怎么会有bug呢?
C语言中的Hello World
用C语言编写Hello World有很多不同的版本,比如维基百科里的版本、《C程序设计语言》一书里的版本,甚至还有1972年贝尔实验室成员Brian Kernighan撰写的版本。
Brian Kernighan撰写的Hello World
下面这个是ANSI C(美国国家标准学会发布的C语言标准)中的版本:
/* Hello World in C, Ansi-style */
#include <stdio.h>
#include <stdlib.h>
int main(void)
puts("Hello World!");
return EXIT_SUCCESS;
这可以说是最严谨的Hello World版本了吧?
它使用(void)来确保main是一种新的声明方式。它使用EXIT_SUCCESS宏指令来表示成功,而不是假设计算机平台使用0。另外,它还使用了适当的头文件声明puts。这个版本试图各方面都做到万无一失。
但它还是有个bug。
C语言里怎么会有bug?
Linux有一个叫“/dev/full”的设备文件,就像它那个有名的表亲“/dev/null”一样,但是当你把数据写入“/dev/full”时,数据并不会扔掉,而是会报错。它的作用就像文件系统中的一个刚刚用完空间的文件:
$ echo "Hello World!" > /dev/full
bash: 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时不同,这里没有得到任何输出,退出状态值为0。这意味着hello world程序成功执行。
但是,它实际上并没有成功。我们可以用strace确认:
$ strace -etrace=write ./hello > /dev/full
write(1, "Hello World!\\n", 13) = -1 ENOSPC (No space left on device)
+++ exited with 0 +++
操作系统报告了“No space”错误,但程序依然执行并返回了0,系统觉得代码成功了。这是个bug啊!
这个bug有多严重呢?
按理说,hello world在任何地方都不是绝对安全的。然而,它确实能打印到标准输出,标准输出可能会被重定向到另一个文件。而现实世界中的文件可能占用了全部空间。如果程序没有检测到这种错误,并通过返回代码报告错误,那么父进程就不会知道子进程失败了,即便系统期望产生的输出已经悄悄丢失了数据,但程序仍会继续运行,就像什么都没发生一样。
例如一个将yaml文件print到标准输出的程序,如果标准输出的空间用完了,输出可能会在某个任意的点被截断,尽管它可能仍然是有效的yaml。所以我们应该期望程序能够检测并报告这种情况。
某些主流语言也有bug
再来看看Python会告诉我们“bug不该悄悄传递”吗?这是Python2:
$ python2 hello.py > /dev/full
close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
$ echo $?
0
它确实向stderr打印了一条信息,尽管这条信息令人困惑,但它也返回了0,这意味着它在告诉运行它的人,它成功退出了。
幸运的是,Python3正确地报告了这个错误,而且还print了一个更赞的错误信息。
$ python3 hello.py > /dev/full
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
OSError: [Errno 28] No space left on device
$ echo $?
120
使用普通教程网站上的hello world程序,又尝试了另外几种语言,测试结果如下:
语言 | 是否有bug | 测试版本 |
C | 是 | (全部) |
C++ | 是 | (全部) |
Python 2 | 是 | Python 2.7.18 |
Ruby | 是 | ruby 2.7.2p137 (2020-10-01修订版5445e04352) [x86_64-linux-gnu] |
Java | 是 | Openjdk 11.0.11 2021-04-20 |
Node.js | 是 | V12.21.0 |
Haskell | 是 | Glorious Glasgow Haskell编译系统,版本8.8.4 |
Rust | 否 | rustc 1.59.0 (9d1b2106e 2022-02-23) |
Python 3 | 否 | Python 3.9.5 |
Perl | 否 | Perl 5,版本32,subversion 1 (v5.32.1) built for x86_64-linux-gnu-thread-multi (with 46 registered patches...) |
Perl 6 | 否 | V2020.12 |
Bash | 否 | GNU bash, version 5.1.4(1)-release (x86_64-pc-linux-gnu) |
Awk | 否 | GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.1) |
OCaml | 否 | 4.08.1 |
Tcl | 否 | 8.6.11 |
C# | 否 | Mono JIT 编译器版本 6.8.0.105 |
编译:lwy
原文链接:
https://blog.sunfishcode.online/bugs-in-hello-world/
以上是关于Hello World程序里居然有bug!的主要内容,如果未能解决你的问题,请参考以下文章