网易首页 > 网易号 > 正文 申请入驻

Rust没拦住的那类Bug:我翻了3个生产项目,发现社区承诺的"零缺陷"有盲区

0
分享至

2021年,一位同事告诉我Rust是"能在Bug诞生前就消灭它们的语言"。三年后,我在三个生产项目里逐行审计,找到了社区说"不存在"的那类错误。

从HN热帖到代码审计


那个648赞的Hacker News帖子"Bugs Rust won't catch"我没急着评论。先打开自己参与维护的三个项目——一个纯Rust项目,两个依赖Rust工具链的项目——拿着帖子的分类清单逐行排查。

结果:找到了。而且正是帖子里列的那几类。

我的核心发现:Rust保证内存安全,但不保证逻辑正确。社区经常把前者包装成后者,这两个不是一回事。我代码里的数字证明了这一点。

第一类:编译器笑着放过的逻辑错误

在一个处理配置文件的Rust CLI工具里,我发现这段代码:

「// Itera sobre los elementos y calcula el "siguiente" índice // El compilador no tiene idea de que este rango está mal fn procesar_ventana(datos: &[u32]) -> Vec { let mut resultado = Vec::new(); // Bug: debería ser datos.len() - 1 para comparar pares // Rust lo compiló feliz. No hay UB, no hay memory error. // Hay un error lógico puro que produce resultados incorrectos. for i in 0..datos.len() { if i + 1 < datos.len() { resultado.push(datos[i] + datos[i + 1]); } } resultado }」

编译器零警告。所有内存访问都合法,生命周期没问题。但业务逻辑是错的——我需要对照项目规格文档才能发现。

这让我想起之前用TypeScript 7 beta跑基准测试的经历:最耗时的错误不是编译器拒绝的,而是编译器热情接受、但语义完全错误的那种。不同语言,同一陷阱。

第二类:算术溢出与边界假设

另一个项目里有段处理像素坐标的代码:

「fn escalar_coordenada(x: u32, factor: u32) -> u32 { x * factor // 溢出在release mode是defined behavior: wrapping }」

Rust的release模式对整数溢出采用wrapping行为(回绕),不是panic。编译器不会拦你,运行时也不会报错。如果你的业务假设"放大后的坐标一定更大",这个假设在u32::MAX附近会静默失效。

我查了cargo.toml,这个项目没开overflow-checks = true。团队显然不知道这个默认行为。

第三类:并发逻辑与数据竞争的区别

在一个依赖Rust写的数据处理管道的项目里,发现这样的模式:

「use std::sync::Arc; use std::thread; fn procesar_en_paralelo(datos: Vec) -> Vec { let compartido = Arc::new(Mutex::new(HashMap::new())); let handles: Vec<_> = datos.into_iter().map(|d| { let clon = Arc::clone(&compartido); thread::spawn(move || { // 每个线程处理自己的数据,但写入同一个map let resultado = calcular(d); clon.lock().unwrap().insert(d.id, resultado); }) }).collect(); // ... join handles }」

Rust的borrow checker确保没有数据竞争(data race)——两个线程不会同时读写同一内存。但逻辑竞争(race condition)呢?如果下游代码假设"map里的键按处理顺序排列",这个假设在并发写入时完全不成立。

编译器没报错。Arc>是合法模式。但业务逻辑里的时序假设错了。

第四类:错误处理的路径遗漏

最隐蔽的在这个纯Rust项目里。团队大量使用?操作符:

「fn cargar_configuracion(ruta: &Path) -> Result { let contenido = std::fs::read_to_string(ruta)?; let parseado: Config = serde_json::from_str(&contenido)?; validar_config(&parseado)?; // 新增的检查 Ok(parsear_con_defaults(parseado)?) }」

问题在最后一行。如果parsear_con_defaults也返回Result,?会提前返回。但调用者拿到Err时,能区分是"文件不存在""JSON语法错误"还是"配置逻辑无效"吗?

我查了调用链,上层用match处理Err时,只打印了通用错误信息。用户看到"配置加载失败",不知道具体哪一步。运维排查时,三个完全不同的根因被埋在同一个错误变体里。

Rust强制你处理错误(Result不能忽略),但不强制你区分错误类型。?操作符让传播变得太容易,有时太容易了。

数字不会说谎

三个项目的审计结果:

• 纯Rust项目(约1.2万行):找到7处逻辑错误,0处内存安全问题

• 依赖Rust工具的项目A(调用Rust写的CLI):3处边界条件错误,其中1处导致生产事故

• 依赖Rust工具的项目B:2处并发时序假设错误,目前未触发但存在风险

12处问题,全部是"Rust承诺不存在的Bug"类别。不是内存泄漏,不是use-after-free,是业务逻辑与代码实现之间的裂缝。

为什么社区会混淆这两件事

我尊重Rust社区的技术深度,但必须指出一个传播现象:内存安全的营销话术被过度外推了。

borrow checker、所有权系统、零成本抽象——这些确实是工程杰作。但它们解决的是特定类别的问题。当技术布道者说"Rust消除Bug",听众容易理解为"消除所有Bug",而实际上只是"消除内存安全类Bug"。

这种混淆在招聘市场更明显。我见过JD写"用Rust重写以减少90%Bug",这个百分比没有来源,也无法验证。我的代码审计显示,逻辑错误占比远高于90%的补集。

对技术选型的实际影响

这不是劝退Rust。我的三个项目会继续用,但会调整工程实践:

• 强制开启overflow-checks = true,或显式使用checked_add等安全算术

• 错误类型必须细分,禁止裸Result>传播

• 关键逻辑路径强制代码审查,不依赖编译器替代人工审计

• 并发代码必须文档化时序假设,并写针对性测试

TypeScript 7的经历让我养成一个习惯:编译器通过只是第一步,语义正确需要第二步验证。Rust项目现在执行同样的两步流程。

给同样被营销话术吸引过的人

如果你正在评估Rust,或者被"零缺陷"承诺打动,建议做一件事:拿你现有的代码库,按Hacker News那个帖子的分类清单审计一遍。不要看别人的例子,用自己的代码。

我的发现可能不代表你的情况。但"内存安全≠逻辑正确"这个等式,在我的代码里被验证了12次。

语言是工具,不是咒语。Rust是很好的工具,但好工具也有适用范围。认清这个范围,比盲目崇拜更能减少生产事故。

你的代码库里,编译器笑着放过、但逻辑明显错误的那类问题,最近一次是什么时候发现的?

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
中国担任安理会5月轮值主席,将聚焦三项重点

中国担任安理会5月轮值主席,将聚焦三项重点

界面新闻
2026-05-02 06:55:49
民宿以“蛇很多”等理由劝退预订客户,官方通报

民宿以“蛇很多”等理由劝退预订客户,官方通报

界面新闻
2026-05-01 08:33:01
孙杨私生子风波升级,处处忍让的张豆豆,终究不再顾及所谓体面

孙杨私生子风波升级,处处忍让的张豆豆,终究不再顾及所谓体面

一盅情怀
2026-04-30 15:59:37
太酷了!70岁法国骑手骑浙江品牌摩托车,穿越多国抵达杭州游西湖

太酷了!70岁法国骑手骑浙江品牌摩托车,穿越多国抵达杭州游西湖

都市快报橙柿互动
2026-05-01 18:25:19
2026年一季度国企数据出炉:利润下滑5.1%,降幅明显大于收入降幅

2026年一季度国企数据出炉:利润下滑5.1%,降幅明显大于收入降幅

风向观察
2026-05-01 11:28:13
硬气拒绝!央视回绝国际足联涨价,中国球迷还能看到世界杯吗?

硬气拒绝!央视回绝国际足联涨价,中国球迷还能看到世界杯吗?

十点街球体育
2026-05-01 22:13:11
为了得到大哥的妻子旺达,伊卡尔迪究极付出了多大的代价?

为了得到大哥的妻子旺达,伊卡尔迪究极付出了多大的代价?

罗氏八卦
2026-05-01 18:05:03
根据53年前颁布的这项法案,今天以后特朗普还能继续打伊朗吗?

根据53年前颁布的这项法案,今天以后特朗普还能继续打伊朗吗?

齐鲁壹点
2026-05-01 08:27:13
5月1日起严查来了!体制内、公职人员必须严守的9条红线(解读)

5月1日起严查来了!体制内、公职人员必须严守的9条红线(解读)

金哥说新能源车
2026-05-01 08:26:32
日本著名马桶公司TOTO杀入芯片行业大获成功

日本著名马桶公司TOTO杀入芯片行业大获成功

爆角追踪
2026-05-01 19:37:18
发现一个特别有意思的规律:
只要是唐嫣出演的剧,

发现一个特别有意思的规律: 只要是唐嫣出演的剧,

小光侃娱乐
2026-05-01 19:45:10
这算不算唱衰国家?俄大V给出战败后的俄罗斯走向

这算不算唱衰国家?俄大V给出战败后的俄罗斯走向

史政先锋
2026-05-01 17:48:27
一朝9帝,全员精神病

一朝9帝,全员精神病

我是历史其实挺有趣
2026-05-01 15:58:48
一到自己就失控?王大雷紧抱郑智让其冷静 随后与泰山球迷起冲突

一到自己就失控?王大雷紧抱郑智让其冷静 随后与泰山球迷起冲突

风过乡
2026-05-02 06:03:01
都想做孟尝君:二代留学豢养书僮,豪门大佬阴养死士硬顶风雷

都想做孟尝君:二代留学豢养书僮,豪门大佬阴养死士硬顶风雷

道术意义
2026-04-30 22:47:25
溺水获救女子开口第一句泪目!救人夫妻身份不简单,获全市表彰

溺水获救女子开口第一句泪目!救人夫妻身份不简单,获全市表彰

奇思妙想草叶君
2026-05-01 16:10:44
举报抽烟的沈女士为何翻车?因为她踩中,网友们最讨厌的1个雷区

举报抽烟的沈女士为何翻车?因为她踩中,网友们最讨厌的1个雷区

观察鉴娱
2026-05-01 08:51:07
一把好牌打得稀烂,直到张军被调查,才懂刘国梁当初选择有多明智

一把好牌打得稀烂,直到张军被调查,才懂刘国梁当初选择有多明智

笑饮孤鸿非
2026-05-02 05:45:34
五一假期第1天,社会上就出现了4个“反常现象”,风向真的变了

五一假期第1天,社会上就出现了4个“反常现象”,风向真的变了

青杉依旧啊啊
2026-05-02 02:01:50
谷歌16年后高调“入驻”中国:引发海内外关注,谷歌为何选择广州

谷歌16年后高调“入驻”中国:引发海内外关注,谷歌为何选择广州

影像温度
2026-05-01 12:39:12
2026-05-02 07:28:49
我是一个养虾人
我是一个养虾人
有态度网友ytd
2032文章数 21关注度
往期回顾 全部

科技要闻

DeepSeek发布多模态论文又连夜删除

头条要闻

美国也搞起"人肉代购" "去墨西哥买中国车"教程疯传

头条要闻

美国也搞起"人肉代购" "去墨西哥买中国车"教程疯传

体育要闻

无奈!约基奇:这要在塞尔维亚 全队早被炒了

娱乐要闻

马筱梅产后身材恢复超好 现身户外直播

财经要闻

GPU神话松动,AI真正的战场变了

汽车要闻

限时9.67万起 吉利星越L/星瑞i-HEV智擎混动上市

态度原创

家居
房产
手机
艺术
公开课

家居要闻

灵动实用 生活艺术场

房产要闻

所有户型全卖爆!海口TOP级豪宅,景观样板间五一全线开放!

手机要闻

记录一场说走就走的旅行 长假影像手机入手指南

艺术要闻

画画的你绝不能错过!色块与笔触的激情之旅!

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版