2025:C 的未來與 C2y——記憶體安全攻防戰#
事件#
2025 年,C 標準委員會展開下一版(C2y,預計 2027 年)的討論。背景是美國 NSA 與 CISA 的記憶體安全報告、白宮 ONCD 呼籲改用記憶體安全語言,以及 Rust 進入 Linux/Windows/Android 核心帶來的全面壓力。C 陣營的回應是「讓 C 更安全」而非「被取代」。
為何重要#
- C2y 討論方向:更強的邊界檢查選項、改進的未初始化偵測、profile 機制(可選的「安全子集」)、與工具鏈(Clang 的 -fbounds-safety、GCC 的靜態分析)更緊密整合。
- 互換性戰線:C++ 與 Rust 互通(CXX-interop)、C ABI 作為語言之間的「拉丁文」——C 不再是最新語言,但仍是所有語言的通用介面。
- 既有堡壘:Linux、Windows、macOS、glibc、SQLite、OpenSSL 等數十億行 C 程式碼仍在服役,C 的維護與安全化是未來數十年的主戰場。
理論與實用原因#
- 理論原因:「記憶體安全」理論(源自 Cyclone、Rust 的所有權與壽命分析)證明安全可以在編譯期保證;C 的路線是「profile + 工具 + 漸進」,在保持「信任程式設計師、零成本抽象」哲學的前提下補上安全網。
- 實用原因:全面重寫數十億行 C 程式碼不切實際(實務證明:重寫的 bug 比修補多),漸進安全化(工具偵測、安全子集、新程式碼用安全語言)是唯一務實路徑。
彌補了什麼缺陷#
C2y 與 C 生態要彌補的是 C 半世紀的根本缺陷——「指標算術自由、邊界不檢查、未初始化、整數溢位、data race」——但這次的手段從「語言特性」轉向「工具與規範」(ASan、MSan、-fbounds-safety、靜態分析)。C 語言從 1972 年「為寫 UNIX 而生」,到 2025 年成為所有語言的通用底層介面與最大的安全化工程對象——這是它半世紀歷史的最佳註腳。
程式範例#
C2y 的方向——工具化安全與 profile 機制的現況(以既有工具示範):
Clang 的 -fbounds-safety——邊界檢查從執行期工具走向編譯期:
/* 以 Clang 的 bounds-safety 擴充(未來 C2y profile 的方向)標註指標 */
#include <stdio.h>
struct buffer {
int * __counted_by(len) data; /* 註明 data 有 len 格——編譯器可檢查越界 */
int len;
};
void write_at(struct buffer *b, int i, int v) {
if (i < b->len)
b->data[i] = v; /* 編譯器驗證 i 在範圍內,插入自動檢查 */
}
C23/C2y 的整數溢位偵測——安全從語言介面補上:
#include <stdckdint.h>
#include <stdio.h>
int main(void) {
long long a = 900000000000LL, b = 900000000000LL;
long long product;
if (ckd_mul(&product, a, b)) { /* 乘法溢位檢查 */
printf("overflow detected\n");
} else {
printf("%lld\n", product);
}
return 0;
}
C ABI 作為語言之間的「拉丁文」——Rust 呼叫 C、C 呼叫任何語言:
/* mathlib.h —— C 的介面定義,Rust/C++/Python 都能綁定 */
long long fib(long long n); /* C ABI:所有語言的通用底層介面 */
// Rust 端:以 C ABI 綁定 C 函式庫
#[link(name = "mathlib")]
extern "C" {
fn fib(n: i64) -> i64; // C 函式宣告
}
fn main() {
let r = unsafe { fib(30) }; // 832040 —— C 函式庫在 Rust 中直接使用
println!("{r}");
}
$ gcc -c -O2 mathlib.c && ar rcs libmathlib.a mathlib.o
$ rustc main.rs -L . && ./main
832040
漸進安全化的實務路線——工具偵測既有程式碼,不必全面重寫:
# 同一份 C 原始碼,三種安全網,零語法改動:
$ gcc -fsanitize=address,undefined prog.c # 記憶體 + 未定義行為
$ clang --analyze prog.c # 靜態分析,編譯期抓錯
$ gcc -fanalyzer prog.c # GCC 的靜態分析器