内存安全大战:Fil-C的20%开销真比Rust的unsafe诚实?

内存安全大战:Fil-C的20%开销真比Rust的unsafe诚实?

💡 原文中文,约2800字,阅读约需7分钟。
📝

内容提要

Fil-C项目为C语言提供内存安全,性能开销约20%,引发与Rust的论战。作者批评Rust零unsafe神话不实,依赖库常含unsafe;C指针操作是安全后门。Fil-C主张全量编译安全,适合存量代码,而Rust侧重新项目。最终讨论聚焦安全与性能的权衡,Fil-C明码标价更显诚实。

🔎

延伸解读

Fil-C的20%开销:存量C代码的“安全保险”

Fil-C通过编译器插入安全检查,为现有C代码提供内存安全,性能损耗约20%。这相当于为存量代码购买“安全保险”,而非像Rust那样要求重写。对于无法重写的庞大C代码库,Fil-C提供了一条务实路径,但20%的代价是否值得,取决于项目对性能的敏感度。

Rust的unsafe:透明但难以避免

Rust的unsafe机制虽然透明可追踪,但实际项目中依赖库普遍使用unsafe,如tokio、serde等。统计unsafe代码容易,但重写不现实。Rust的零unsafe神话在实战中难以实现,unsafe更像是一种免责声明,而非彻底的安全保障。

安全C子集:理论可行,实践困难

虽然理论上可以定义C的安全子集(如GLSL),但实际中普通项目难以像WebKit那样投入大量专家进行代码审查。安全子集的实践门槛高,普通开发者难以掌握,因此Fil-C的全量编译安全方案更具普适性。

性能与安全的权衡:明码标价更诚实

Fil-C的20%开销是明确的性能代价,而Rust的零成本抽象依赖unsafe的自觉使用。两者都不是零代价的完美方案。Fil-C将成本透明化,让开发者权衡取舍,这种明码标价的方式比宣称零开销更诚实。

Q&A

Fil-C项目是什么?它如何为C语言提供内存安全?

Fil-C是一个为C语言提供内存安全的编译器项目,它通过编译器魔法在编译时插入安全检查,将整个C语言重新编译为安全版本,性能开销约为20%。它旨在让存量C代码无需重写即可获得内存安全。

Fil-C的性能开销是多少?这个开销值不值?

Fil-C的性能开销约为20%。对于这个开销是否值得,存在争议:有人认为20%太贵,不如直接用Rust;也有人认为考虑到内存安全漏洞造成的经济损失,20%的代价是划算的。Fil-C作者认为这是明码标价的保险费用,比号称零开销的方案更诚实。

为什么说Rust的零unsafe神话不现实?

因为实际发布的Rust程序要么自己使用unsafe,要么依赖的库大量使用unsafe。例如,HTTP解析库、游戏引擎的物理碰撞检测库、tokio异步运行时、serde序列化库等底层依赖都使用了unsafe来优化性能。用cargo-geiger扫描依赖树,会看到大量红色警告。因此,零unsafe的Rust程序几乎不存在。

C语言的指针算术为什么是安全后门?

C语言的指针算术(如指针加减、强转)在标准中被视为合法操作,编译器不进行拦截,因此每个指针操作都可能成为内存安全漏洞的入口。这些操作密度极高,程序员几乎无法避免,导致C语言整个代码都充满风险。相比之下,Rust将危险操作集中在unsafe关键字中,至少能明确危险区域。

Fil-C与Rust在内存安全路线上的主要区别是什么?

Fil-C主张全量编译安全,通过编译器插入检查,让存量C代码原地升级安全属性,适合存量代码;Rust则通过类型系统和unsafe关键字提供安全保证,但依赖开发者自觉,更适合新项目。Fil-C的代价是约20%的性能开销,而Rust的unsafe可能带来隐藏风险。

Fil-C作者如何回应Rust社区关于unsafe透明可追踪的观点?

Fil-C作者指出,虽然Rust有cargo-geiger等工具可以统计unsafe代码,但很少有人真正去统计,因为统计结果会让人崩溃:依赖的tokio、serde、regex等库都大量使用unsafe,统计后也无法重写。他认为Rust的unsafe机制是一种免责声明,而Fil-C则通过全量编译安全来避免这种问题。

Fil-C的20%开销被比喻成什么?为什么说它比号称零开销的方案更诚实?

Fil-C的20%开销被比喻成保险费用。它明码标价,承诺覆盖所有内存安全问题,而Rust的零成本抽象依赖unsafe自觉,C语言则完全没有安全保障。Fil-C作者认为,把成本摆上桌面比那些号称零开销的方案更真诚,因为后者往往隐藏了风险。

🏷️

标签

➡️

继续阅读