开源 mysql nginx Windows php Python Android 微软 编程 程序员 Ubuntu shell linux apache google Firefox centos wordpress java 云计算

編程語言和胖手指

水星探索項目中一段Fortran代碼裏的逗號被寫成了點號,影響了運算的準確性,導致太空探測器無法到達更遠的軌道。出現這種事情的幾率有多大?一種編程語言的設計在多大程度上會影響程序正確性和導致相似的事件?最近發表在第四屆International Workshop on Evaluation and Usability of Programming Languages and Tools上的一篇論文中,我展示了一些研究發現:通過往由各種不同語言編寫的類似程序中隨機的制造一些幹擾信息,看編譯器或運行系統能否發現由這些幹擾引起的錯誤,或者最終導致了程序輸出了錯誤的結果。

在由我和我的同事 Vassilios Karakoidas、Panagiotis Louridas共同指導的這項研究中,我們首先選擇了10中流行的編程語言,以及用它們寫出的一批程序。我們選擇這些語言的條件是基於一篇IEEE Spectrum文章裏 提供的數據(由軟件研究公司TIOBE建立的一個索引目錄)、出現在Powell’s Books書名中的數量、IRC在線討論中引用的數量,以及Craigslist中招聘職位的數量。在這樣一個流行語言的大集合中,由於一些可操作性的原 因,部分語言被排除在外。根據流行度索引,這個集合大概能覆蓋所有語言的71%到86%。

然後我們從Rosetta Code wiki中尋找我們研究的這10種語言寫成的執行相同任務的各種源代碼。用Rosetta Code這個網站的創辦人自己的話,這個網站的目的就是搜集用不用的各種語言來完成同一種任務的代碼,展示它們的相似和不同,幫助那些研究基礎工作的人了解問題的另一種解決方案。

我 們的下一步是要制造一個代碼幹擾器:一個能系統的往代碼裏隨機引入各種隨機混亂的工具。幹擾器能替換標誌符,把一些數字加一,隨機改變字符或把字符串替換成相似的東西或隨機的串。最後,我們把幹擾器應用到我們搜集的代碼裏,檢查這些被修改後有錯誤的代碼是否能被編譯器或運行環境檢測到,或是否導致了錯誤的 輸出。

理論上,我們人工引入的這些錯誤是模擬現實生活中的很多具體表現。錯誤拼寫——“胖手指”——就是一個很常見的例子。另外的場景包括 馬虎大意,自動重構錯誤(特別是在像C和C++這些語言裏,自動重構是很難正確無誤的實現的),復雜的編輯器命令導致的意外失誤,或搜索-替換操作造成的 錯誤,甚至還包括貓踩著鍵盤上產生的後果。

總計我們一共測試了136個任務實現,嘗試了2萬8千種幹擾操作,其中成功的有261,667 (93%)個。被幹擾的程序中有90,166 (32%)個編譯通過或語法上沒有發現異常。60,126 (67%, 或 總共被幹擾的數量的23%)個能正常的結束運行。 18,256個輸出了完全無異的結果,表明幹擾沒有對程序產生任何影響。其余的,41,870 個程序 (能運行的70%, 總數的16%)編譯和運行都沒有問題,但輸出了結果錯誤。

編程語言和胖手指

上 圖顯示了對各種語言的統計結果,是按失敗情況統計:成功的編譯或執行,沒有捕獲程序中的錯誤,導致輸出了錯誤的結果。上圖驗證了我們一些非常直覺的看法。 強靜態類型語言(JAVA, Haskell, C++)比那些弱的或動態類型語言(Ruby, Python, perl, PHP, 和 JavaScript)能在編譯器捕獲更多的錯誤。稍微有點意外的是,C語言出現在了中間位置,驗證了一個被很多人相信的觀點:C語言的類型系統並不像它 的眾多追隨者(包括我)認為的那樣強。然而,C語言在運行期卻拋出了大量的錯誤,導致最終它的不正確輸出結果的比率跟那些強類型語言的相似。

這 還有一副類似的統計圖,統計的是運行時各種語言的表現。同樣,相比起強類型語言,弱類型語言更傾向於仍能無異常(崩潰或拋出異常)的運行。根據這兩個統計表可以看出,弱類型語言在輸出結果上將會有更高的錯誤率。相比起C++或C#,php的錯誤率是36%,而C++的是8%,C#是10%,用像PHP這樣語法上不是很嚴格的語言寫成的應用,雖然充分利用了這些弱類型語言帶來的方便性,但不經意的拼寫錯誤也會很容易溜進產品代碼裏。總的看來,動態腳本語言跟 強靜態類型語言比起來差距很大。這可能是我們只在較高層面測試這些腳本語言特征有關。

我們對這些數據做了進一步分析,發現了下面一些事情。

這些在靜態語言和動態語言幹擾測試對比結果在統計學上有重要意義。這驗證了靜態語言比動態語言更容易發現錯誤。
C#的表現更像C和C++,而不是Java,盡管它外觀上跟後者更相似。
Haskell 的表現跟Java很相似。
統計數據顯示在靜態類型語言間被幹擾表現有明顯不同,比如C和C++間,C++和Java間,Haskell和Java間等。然而,動態語言間卻沒有一個可比較的模式。借用托爾斯泰的一句話,它們看起來各有各不同。
然而,我想我們的研究最重要的成果是,通過對具有可比性的語言進行幹擾測試,提供了對編程語言的設計進行評價的數據資料。

延伸阅读

    评论