測試 C、Python、Java 等 16 種程式語言的 Hello World:7 種存在 Bug?
譯者 | 張潔
責編 | 屠敏
Hello World 可能是最簡單的計算機入門程式。幾十年來,許多人在開始使用新的程式語言時,編寫的第一個程式通常是 Hello World。
這不起眼的入門程式沒有 Bug,對嗎?
圖片來自 sunfishcode 的部落格
畢竟,Hello World 程式只做一件事。怎麼會有 Bug?
萬萬沒想到,有開發者在好奇心驅動下,測試了 16 種常用的語言後,竟然在裡面檢測出了 7 種程式語言的 Hello World 帶有 Bug。
以 C 語言中的 Hello World 程式為例
首先,以 C 語言為例來測試。事實上,用 C 語言寫 Hello World 有很多不同的版本,如維基百科搜尋顯示的版本、《C 程式設計語言》(也簡稱 K&R)一書中的 Hello World,甚至還有從 1974 年貝爾實驗室備忘錄中引入的最古老的 C 語言 Hello World 程式。
圖片來自 sunfishcode 的部落格
這是 “ANSI C ”(
美國國家標準協會和國際標準化組織對 C 語言釋出的標準
)中的 Hello World 程式寫法:
/* Hello World in C, Ansi-style */
#
include
#
include
int
main
(
void
)
{
puts
(
“Hello World!”
);
return
EXIT_SUCCESS;
}
對於業界而言,這應該是最標準 C 語言 Hello World 的版本。
它使用“(void)”來顯示 main 是一種新型宣告方式。這個版本使用 EXIT_SUCCESS 返回值來表示成功,而不是使用 0。根據 C 語言標準,這其實沒有必要,不過在此我們也不做更改了。除此之外,它還使用了適當的標頭檔案聲明瞭 puts 函式。
這個版本試圖把所有的步驟都做到完美。
然而,它裡面還是有一個 Bug。
C 語言中的 Bug 從何而來?
Linux 有一個有趣的裝置檔案,叫做“/dev/full”,跟“/dev/null”(
程式設計師群體中行話叫做黑洞,即丟棄一切寫入其中的資料,讀取它會立即得到一個 EOF
)非常像,但是當你將資料寫入到“/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,這以為系統認為這一段程式碼是成功的。
顯而易
見,這是一個 B
ug!
那麼,這個 Bug 有多嚴重呢?
可
以
說
,Hello World 不應該作為標準的測試程式碼,因為它並不是
絕
對的安全
。
此話應該從何說起?想必很多程式設計師在初次學習程式設計的時候,大多數會用 Hello World 程式來試一下。這也導致了 Hello World 常被開發者用來檢測程式的標準輸出,但是因為此時 Hello World 程式存在 Bug,所以 prints 的標準輸出往往可能會被重定向到另一個檔案。
譬如,現實世界中,
如果檔案佔用了全部的空間。此時用 Hello World 程式來檢測,最終並沒有檢測任何問題
,那麼該程式碼的父程序將不知道子程序失敗了,會繼續執行,即使系統期望產生的輸出內容已經悄悄地丟失了資料,但程式還是像什麼都沒有發生一樣。
舉個例子,編寫一個程式,其中主要是
prints
一個 yaml 檔案到標準輸出。如果標準輸出的空間用完了,輸出可能會在某個任意的點被截斷,儘管它仍是有效的 yaml。所以我們期望程式能夠檢測並報告這種情況。
7 種主流語言常見的 Hello World 程式都有 Bug?
除了 C 語言之外,Python 告訴我們“Bug 不應該被無聲地忽視”,下面是 Python 2 的測試示例:
$ python2 hello。py >
/dev/full
close failed
in
file object
destructor:
sys。excepthook is missing
lost sys。stderr
$ echo $?
0
它確實向 stderr 輸出了一條資訊,並且還是一條令人困惑的資訊。然而,它也返回了 0,這意味著它在告訴執行它的人,它成功退出了。
幸運的是,Python 3 正確地報告了錯誤,而且還顯示了一個更漂亮的錯誤資訊。
$ python3 hello。py >
/dev/full
Exception ignored
in:
<_io。TextIOWrapper name=
‘
mode=
‘w’
encoding=
‘utf-8’
>
OSError:
[Errno
28
] No space left on device
$ echo $?
120
另外,我也還是使用普通教程網站上的 Hello World 程式,嘗試了其他幾種程式語言,以下是測試結果:
原文連結:
https://blog。sunfishcode。online/bugs-in-hello-world/
宣告:本文為 CSDN 翻譯,轉載請註明來源。
—
END
—
《新程式設計師001-004》全面上市,對話世界級大師,報道中國IT行業創新創造