C.3 軟體缺陷與安全關鍵系統案例#
軟體工程史上,代價最高昂的教訓幾乎都集中在「安全關鍵系統」(Safety-Critical Systems):一旦軟體出錯,後果不是商譽損失,而是人命、巨額資金或不可逆的災難。本節選入四個經典案例:一架火箭、一部醫療儀器、一台繞行火星的太空船與一座核電廠,其共同的教訓在於——在後果不可逆的系統中,單一程式缺陷就足以造成全面性災難(呼應 4.1 節正確性、9.3 節驗證機制)。
案例一:阿利安 5 號火箭——3.7 億美元的型別溢位#
背景:1996 年,歐洲太空總署(ESA)發射阿利安 5 號(Ariane 5)運載火箭,發射後僅 37 秒便偏離軌道並自動引爆,損失約 3.7 億美元。
技術真相:禍首只是一段重用的程式碼。團隊直接重用舊型號阿利安 4 號的慣性參考系統程式碼,其中一段將代表「水平速度」的 64 位元浮點數強制轉型為 16 位元有號整數。阿利安 5 號的加速性能遠勝 4 號,數值超出 16 位元整數上限(32,767),觸發溢位例外;系統未處理該例外,主機當機後輸出的診斷數據又被導航系統誤讀為「火箭姿態嚴重偏差」,自動啟動自毀程序。
啟示(連結本書):程式碼重用必須基於對新版環境的重新驗證。在 4 號機正常跑的型別假設,在 5 號機完全不成立(見 2.4 節「邊界條件」、4.1 節型別安全)。這也與 AI 時代直接相關:AI 產出的程式碼往往大量複製既有模式,若不驗證「新環境的邊界假設」,就會重演阿利安 5 號式的悲劇——「編譯過 = 正確」的假設在安全關鍵系統裡極其危險。
案例二:Therac-25——競態條件如何傷害病人#
背景:加拿大原子能公司(AECL)推出的 Therac-25 是電腦控制的放射治療機。1985 至 1987 年間,它導致至少六起嚴重輻射過量事故,多名患者重傷或死亡。
技術真相:Therac-25 刪除了舊型號的硬體安全連鎖開關,完全改用軟體控制。操作員以極快速度輸入並修改治療參數時,軟體的併發執行緒產生競態條件(Race Condition):系統在「實體遮蔽板尚未移動到位」時就啟動高能量電子束,直接將數百倍安全劑量的輻射注入病人體內。
啟示(連結本書):安全關鍵系統的這三個鐵律至今依然適用——
- 硬體備援不能省:把安全寄託在單一軟體上是把雞蛋放在同一個籃子(見 3.3 節冪等性、9.2 節約束機制)
- 競態條件必須嚴肅對待:併發不是選項,是必須被設計與測試的事實(見 1.1 節、3.3 節)
- 防禦性程式設計:出錯時要「安全地停下」,而不是「繼續跑」——這正是 9.4 節「糾正機制」的工程根源
案例三:火星氣候軌道器——英制與公制混用的致命介面#
背景:1999 年,NASA 造價 1.25 億美元的火星氣候軌道器(Mars Climate Orbiter)在進入火星軌道時失蹤,隨後被證實過於貼近火星大氣而燒毀。
技術真相:不是複雜的物理公式錯誤,而是系統間介面的單位不統一。地面控制軟體(承包商洛克希德·馬丁)輸出的是英制「磅·秒」,而 NASA 主航太軟體假設收到的是公制「牛頓·秒」。4.45 倍的單位偏差在數個月的軌道修正計算中累積,最後把太空船推到錯誤高度。
啟示(連結本書):介面契約必須明確到「型別」層級——與其讓兩套系統都傳「float」,不如傳「NewtonSeconds」這種自定型別(見 3.5 節介面設計、4.1 節強型別)。這正是現代語言引入型別系統、微服務引入 OpenAPI 契約(12.3 節)的核心動機。對 AI Agent 而言,讓 AI 呼叫工具時理解「單位、欄位、合約」仍是第 8 章工具定義(Tool Definition)最重要的工程之一。
案例四:車諾比核電廠——把「安全」設計反了#
背景:1986 年,蘇聯車諾比核電廠 4 號反應爐爆炸,史上最嚴重的核災。一般歸因於操作失誤,但更深層的是設計本身。
技術真相:該型 RBMK 反應爐具「正空穴係數」——冷卻水變成水蒸氣時反應功率不降反升;更致命的是控制棒末端的石墨尖端設計:按下緊急停止按鈕 AZ-5 插入控制棒時,石墨端會先排開冷卻水、在第一秒短暫「加劇」反應,導致功率不降反爆。這是一次「緊急動作反而更危險」的失敗安全(Fail-safe)設計錯誤。
啟示(連結本書):故障安全的設計原則是:系統出錯時,預設物理狀態必須自動趨向安全,而非趨向危險(見 9.2 節「約束」、13.2 節權限控管)。這也提醒我們:當一個系統把「救命的按鈕」設計成「引爆的按鈕」時,再多的操作規範都救不了它——安全必須從架構層級設計進去。
一張表格看懂「安全關鍵系統」四案例#
| 案例 | 核心缺陷 | 教訓(對應章節) |
|---|---|---|
| Ariane 5 | 型別溢位 + 未處理例外 | 重用必須重新驗證邊界(2.4、4.1) |
| Therac-25 | 競態條件、卸責硬體 | 併發安全 + 硬體備援(3.3、9.2) |
| 火星軌道器 | 介面單位不一致 | 介面契約與強型別(3.5、4.1) |
| 車諾比 | 緊急機制反而加劇災難 | 架構層級的 Fail-safe(9.2、13.2) |
想一想#
- Ariane 5 告訴我們「在新環境重用舊程式碼」有多危險。AI 生成程式碼時常常複製既有慣用寫法,這與 Ariane 5 的重用模式相似嗎?你如何避免自己(或 AI)重蹈覆轍?
- Therac-25 刪掉硬體安全連鎖、改用軟體控制。這種「以軟體取代硬體保證」的趨勢,在現代產品(例如自駕車、CI/CD 自動部署)裡是否也存在?該如何看待?
- 車諾比案例中「緊急動作反而更糟」。你能舉出一個現代軟體系統裡「本意良好、機制卻會幫倒忙」的自動化設計嗎?它該如何被修正?
本章小結#
四個案例的共同點,是「錯誤被允許的容忍度為零」。安全關鍵系統要求工程師不只在「正常情況」下驗證,更要在「異常、極端、重疊錯誤」下思考——邊界條件(2.4)、併發安全(3.3)、介面契約(3.5)、驗證與糾正機制(9.2、9.4)。當我們把愈來愈多自治權交給 AI Agent 時,這四條教訓的價值非但沒有降低,反而成為 Harness 設計的座標:約束該怎麼設、驗證該怎麼做、出了錯如何安全停下。