程序员圈子里流传一句老话:C 语言给你足够的绳子吊死自己,C++ 给你更多绳子,顺便多送几根。绳子是什么?就是你手里那块内存的所有权。malloc 出来的那 64 个字节,到底归谁管、谁负责释放、释放之后别人还能不能摸——这些问题 C 语言一概不管,全凭程序员自觉。于是 we have 段错误(segmentation fault)、use-after-free、double free,这仨兄弟承包了安全圈几十年的头条。
freeCodeCamp 的这条《Learn Rust Programming - Complete Course》讲的就是这个问题的第三种解法:Rust。它不靠程序员自觉(C 的路线),也不靠垃圾回收器(Java/Go 的路线),而是让编译器在你按下保存键的那一刻,就把内存违规全部拦下。这门课在 YouTube 上拿了 124 万+播放,评论区最常见的一句话是"原来我之前写的代码里埋了这么多雷"。
说实话,Rust 的入门资料不少,但多数要么是语法手册,要么直接跳进异步和 trait 泛型的深水区。这条课的价值在于它按"内存模型优先"的顺序讲:先把所有权(ownership)这个灵魂概念立住,剩下的语法糖都是围绕它展开的。这也是我把它推荐给通信行业同事的原因——我们写的协议栈代码,天天跟 buffer 的生命周期打交道,use-after-free 不是抽象名词,是凌晨三点的告警电话。
| 项目 | 内容 |
|---|---|
| 视频标题 | Learn Rust Programming - Complete Course 🦀 |
| 频道 | freeCodeCamp.org |
| 时长 | 完整课程长课(freeCodeCamp 系列均为数小时级系统课) |
| 播放量 | 124万+(截至2026年9月底) |
| 核心主题 | Rust 所有权系统:不靠 GC 的编译期内存安全 |
以下基于课程主题逐点展开。课程主线内容用自己的话重新组织,延伸分析会单独标注。
一块内存,谁来释放?这个问题只有三种答案。第一条路:手动。C/C++ 的方式,malloc 和 free 配对,快、可控,但人一定会犯错——微软安全响应中心(MSRC)2019 年披露的数据显示,其产品约 70% 的严重安全漏洞属于内存安全问题;谷歌 Chrome 团队 2020 年的分析也给出了相近的数字。第二条路:垃圾回收。Java、Go、Python 把释放交给运行时,安全了,但代价是 GC 线程随时可能介入,带来停顿和内存开销。第三条路:Rust 的编译期裁定——释放时机编译期就确定,生成的机器码里根本没有 GC,运行时零额外开销。(以上三条路线是课程引入的标准框架;两个 70% 的数据是我的补充,均为公开报道。)
Rust 的所有权系统只有三条规则,课程用不了十分钟就讲完了,但它们能推导出整个语言的内存行为:第一,Rust 里每一个值都有且只有一个所有者(owner),通常就是绑定它的那个变量;第二,同一时刻一个值只能有一个所有者,不存在"两个人共同负责"这种模糊地带;第三,所有者离开自己的作用域时,值被自动丢弃(drop),内存当场释放。注意第三条的实现方式:它就是 C++ 的 RAII(资源获取即初始化)思想的正统继承——资源绑定在栈变量的生命周期上,栈帧一弹,资源自动还。("RAII 渊源"是我的延伸,课程层面通常点到为止。)
这是 C 程序员转 Rust 的第一记闷棍。看这段代码:
let s1 = String::from("hello");
let s2 = s1; // 所有权从 s1 过户给 s2
println!("{}", s1); // 编译错误:borrow of moved value: s1
在 C 里,这句赋值就是浅拷贝一个指针,两份指针指向同一块堆内存,谁负责 free?经典的悬案。Rust 的答案简单粗暴:s2 = s1 的那一刻,所有权整体移动(move),s1 从此作废,编译器看到再用就直接报错。你不用记住规则然后祈祷自己遵守——是编译器替你检查,违规的代码根本编译不过。顺带一提,整数、浮点这类纯栈上数据实现了 Copy trait,赋值时自动按位复制,不走 move。这块的微妙之处在于"为什么 String 走 move 而数字不走",课程里有专门的段落讲堆和栈的分工,值得细看。
总是过户太麻烦了——我调个函数打印字符串长度,总不至于把字符串都送出去。所以 Rust 有借用(borrowing):临时把值的使用权借出去,所有权不动。共享借用 &T 可以同时存在任意多个,大家一起读,相安无事;可变借用 &mut T 全场只许一个。而且两者互斥——有人读着的时候,不许任何人写:
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s; // 两个只读借用,没问题
let r3 = &mut s; // 编译错误:cannot borrow as mutable
println!("{} {}", r1, r2);
这个"读写互斥"规则看着严苛,实际上就是数据库的共享锁/排他锁搬进了类型系统——写通信协议的同事应该秒懂:这正是并发读写共享 buffer 时防数据竞争的同一套逻辑,只不过 Rust 把它从运行时的锁纪律提前成了编译期的硬约束。("锁类比"是我的延伸分析,不是课程原话。)
C 的经典惨案:函数返回一个指向局部变量的指针,函数一返回栈帧销毁,指针变成悬垂指针(dangling pointer),读写它都是未定义行为——而且编译器一声不吭。Rust 里同样的代码直接编译失败,错误信息会明确告诉你"返回的引用活不过被借的数据"。这就引出了生命周期(lifetime)概念:编译器为每个引用推断它有效的区域,确保引用存在期间,数据一定还活着。多数场景编译器自动推断,搞不定时才需要手写 'a 标注。课程在这块给了多个"故意写错再看报错"的例子,强烈建议跟着敲一遍——Rust 的编译错误信息是出了名的教学级质量,报错本身就是一门课。
一门语言如果只会说"不许",是活不下去的。真实世界里有无法用单一所有者表达的结构:双向链表两个节点互相指、多线程共享缓存池。Rust 的解法是引用计数类型 Rc<T>(单线程)/Arc<T>(多线程原子计数,"Arc"即 Atomic Reference Count)让多个所有者共存,再配合 RefCell<T> 把借用检查从编译期挪到运行时。课程把这部分讲得很实在:这些工具是"有代价的让步"——Rc 循环引用会泄漏,RefCell 违规会 panic,编译器把绳子递给你,但明确告诉你这根绳子不再免费。(这段的补充说明是我加的,课程主线是讲用法。)
延伸一点课本上不太讲的东西。Rust 的 move 语义在类型理论里叫仿射类型(affine type)——每个值最多使用一次,可以不用,但不能用两次。它脱胎于线性类型系统(linear type system)的研究,Philip Wadler 上世纪九十年代就把这套路子讲清楚了;2010 年前后 Mozilla 的 Graydon Hoare 把它落地成 Rust,再经 Niko Matsakis 等人持续打磨出借用检查器的现代形态(含 2017 年后的 NLL,非词法生命周期,让报错点更贴近真正违规的那一行)。你在 Rust 里感受到的那些"别扭",不是设计失误,而是四十年来类型论对"内存安全"这道题的最严格解。
Rust 到底有没有用?看几个高置信的公开事实。谷歌 2022 年底在 Android 安全博客披露:随着 Rust 代码在 Android 里铺开,内存安全漏洞占比从 2019 年的 76% 一路降到 2022 年的 35%,新代码几乎不再贡献内存漏洞。Linux 内核从 6.1 版本(2022 年底)正式合入 Rust 支持,成为历史上第一种被内核接纳的带 GC 之外内存模型的语言。微软在 2023 年宣布用 Rust 重写 Windows 内核的部分组件,理由同样是那 70%。AWS 的轻量级虚拟化底座 Firecracker、Discord 2020 年公开的重构案例(Go 换 Rust 后 Read States 服务的延迟尖峰随 GC 一起消失),都属于同一张成绩单。Rust 也连续多年蝉联 Stack Overflow 开发者调查"最受喜爱语言"榜首。
flowchart TD
A["一块内存由谁释放"] --> B["手动管理 C路线"]
A --> C["垃圾回收 GC路线"]
A --> D["编译期裁定 Rust"]
B --> B1["use-after-free"]
B --> B2["double free"]
C --> C1["停顿与运行时开销"]
D --> E["所有权三规则"]
E --> F["每个值唯一所有者"]
E --> G["赋值即过户 Move"]
E --> H["出作用域自动释放"]
G --> I["还想用 借用"]
I --> J["共享借用 可多个"]
I --> K["可变借用 仅一个"]
J --> L["读写互斥 竞争无从发生"]
K --> L
L --> M["悬垂引用编译期拦截"]
M --> N["零运行时开销的内存安全"]
给协议栈和网元开发者。电信代码是 use-after-free 的重灾区:定时器回调摸一块已被释放的 buffer、SCTP 关联释放后还有事务引用它——这类 bug 的共同点是测试时永远不炸,上了网就炸。Rust 的所有权模型把"这块内存现在归谁"变成编译器里的显式事实,定时器持有引用,编译器就要求这个引用活得过数据,否则拒绝编译。与其在代码评审里靠人眼盯生命周期,不如让机器盯。
给所有后端/系统程序员。不必全盘重写。Linux 内核和微软的路线都是渐进式:新模块用 Rust 写,边界处包一层 FFI,老代码按风险逐个替换。个人学习路径建议:先把这条课过一遍,然后直接上官方书《The Rust Programming Language》(免费在线,doc.rust-lang.org/book),配合 rust-lang/rustlings 的小练习边写边错——跟借用检查器搏斗的头两周是必经之路,撑过去之后你会发现自己写 C++ 时也开始下意识地问"这块谁负责释放",这就是 Rust 给你的思维upgrade。
代价也要说清楚。Rust 的编译期检查意味着前期开发速度明显下降、复杂图状结构写起来费劲、编译时间偏长。如果你们的场景是短生命周期的业务胶水代码,Go/Python 依然是更划算的选择;但只要涉及长生命周期共享内存、多线程、以及"出 bug 就是安全事故"的场合,这套纪律的回报率极高。
Rust 最大的创新不是更快或更安全,而是把"谁负责释放这块内存"从一个运行时的祈祷,变成了一个编译期的数学证明——这条课教会你的就是如何向编译器证明它。
本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
