Speaker intro and general approach
讲者介绍与课程整体思路
What you’ll learn: Course structure, the interactive format, and how familiar C/C++ concepts map to Rust equivalents. This chapter sets expectations and gives you a roadmap for the rest of the book.
本章将学到什么: 课程结构、互动式学习方式,以及熟悉的 C / C++ 概念如何映射到 Rust。本章先把预期对齐,再给出整本书的路线图。
- Speaker intro
讲者背景- Principal Firmware Architect in Microsoft SCHIE (Silicon and Cloud Hardware Infrastructure Engineering) team
微软 SCHIE(Silicon and Cloud Hardware Infrastructure Engineering)团队的首席固件架构师。 - Industry veteran with expertise in security, systems programming, CPU and platform architecture, and C++ systems
长期深耕安全、系统编程、CPU 与平台架构,以及 C++ 系统开发。 - Started programming in Rust in 2017 at AWS EC2 and have been deeply invested in the language ever since
2017 年在 AWS EC2 开始写 Rust,之后就一直深度投入这门语言。
- Principal Firmware Architect in Microsoft SCHIE (Silicon and Cloud Hardware Infrastructure Engineering) team
- This course is intended to be as interactive as possible.
这门课会尽量做成高互动形式。- Assumption: You know C, C++, or both
默认前提:已经熟悉 C、C++,或者两者都熟。 - Examples deliberately map familiar concepts to Rust equivalents
示例会故意沿着熟悉概念往 Rust 对应物上带,减少认知跳跃。 - Please feel free to ask clarifying questions at any point of time
任何时候都可以插进来问澄清问题。
- Assumption: You know C, C++, or both
- Continued engagement with engineering teams is encouraged.
也希望后续能继续和工程团队深入交流。
The case for Rust
为什么值得认真看 Rust
Want to skip straight to code? Jump to Show me some code
想直接看代码? 可以跳到 给点代码看看。
Whether the background is C or C++, the core pain points are basically the same: memory-safety bugs that compile cleanly, then crash, corrupt, or leak at runtime.
不管主要背景是 C 还是 C++,最烦人的核心问题其实都差不多:内存安全 bug 编译时屁事没有,运行时却能把程序搞崩、把数据搞坏、把资源搞漏。
- Over 70% of CVEs are caused by memory-safety issues such as buffer overflows, dangling pointers, and use-after-free.
超过 70% 的 CVE 都和内存安全问题有关,比如缓冲区溢出、悬垂指针、释放后继续使用。 - C++
shared_ptr、unique_ptr、RAII and move semantics are useful steps forward, but they are still bandaids, not cures.
C++ 的shared_ptr、unique_ptr、RAII 和移动语义确实进步很大,但本质上还只是 止血贴,不是根治方案。 - Gaps such as use-after-move, reference cycles, iterator invalidation, and exception-safety hazards are still left open.
像 use-after-move、引用环、迭代器失效、异常安全这些口子,依然都在。 - Rust keeps the performance expectations of C / C++, while adding compile-time guarantees for safety.
Rust 保住了 C / C++ 这一级别的性能,同时把安全保证提前到 编译期。
📖 Deep dive: See Why C/C++ Developers Need Rust for concrete vulnerability examples, the full list of problems Rust eliminates, and why C++ smart pointers still fall short.
📖 深入阅读: 为什么 C / C++ 开发者需要 Rust 里有更具体的漏洞案例、Rust 能消灭的问题清单,以及为什么 C++ 智能指针依然不够。
How does Rust address these issues?
Rust 是怎么处理这些问题的
Buffer overflows and bounds violations
缓冲区溢出与越界访问
- All Rust arrays, slices, and strings carry explicit bounds information.
Rust 的数组、切片和字符串都带着明确的边界信息。 - The compiler inserts checks so that a bounds violation becomes a runtime panic, never undefined behavior.
编译器会插入边界检查,越界访问顶多触发 运行时 panic,不会悄悄掉进未定义行为。
Dangling pointers and references
悬垂指针与悬垂引用
- Rust introduces lifetimes and borrow checking to eliminate dangling references at compile time.
Rust 通过生命周期和借用检查,在 编译期 直接消灭悬垂引用。 - No dangling pointers and no use-after-free — the compiler simply refuses to accept such code.
没有悬垂指针,也没有释放后继续使用;这种代码编译器压根就不让过。
Use-after-move
移动后继续使用
- Rust’s ownership system makes moves destructive. Once a value is moved, the original binding is unusable.
Rust 的所有权系统把 move 设计成 破坏性转移。值一旦被移动,原绑定立刻失效。 - That means no zombie objects and no “valid but unspecified state” nonsense left behind.
这样就不会留下什么僵尸对象,也不会冒出那种“有效但状态未指定”的烂摊子。
Resource management
资源管理
- Rust’s
Droptrait is RAII done properly: resources are released automatically when they go out of scope.
Rust 的Droptrait 把 RAII 真正做扎实了:资源一出作用域就自动释放。 - It also blocks use-after-move, which is exactly the hole C++ RAII still cannot seal completely.
同时它还和所有权系统联动,直接堵上了 C++ RAII 依然兜不住的 use-after-move 问题。 - No Rule of Five ceremony is required.
也不用再背什么 Rule of Five 套路。
Error handling
错误处理
- Rust has no exceptions. Errors are values, usually represented as
Result<T, E>.
Rust 没有异常系统,错误就是值,最常见的载体就是Result<T, E>。 - Error paths stay explicit in the type signature instead of藏在控制流后面。
错误分支会直接写进类型签名里,而不是躲在隐蔽控制流后面。
Iterator invalidation
迭代器失效
- Rust’s borrow checker forbids modifying a collection while iterating over it.
Rust 的借用检查器会 禁止边遍历边改容器 这种写法。 - A whole class of C++ 老毛病 therefore cannot even be expressed in valid Rust.
这类在 C++ 代码库里反复出没的老毛病,在 Rust 里连合法代码都写不出来。
#![allow(unused)]
fn main() {
// Rust equivalent of erase-during-iteration: retain()
pending_faults.retain(|f| f.id != fault_to_remove.id);
// Or: collect into a new Vec (functional style)
let remaining: Vec<_> = pending_faults
.into_iter()
.filter(|f| f.id != fault_to_remove.id)
.collect();
}
Data races
数据竞争
- The type system prevents data races at compile time through
SendandSync.
类型系统通过Send和Sync在 编译期 阻止数据竞争。
Memory Safety Visualization
内存安全可视化
Rust Ownership — Safe by Design
Rust 所有权:从设计上就偏安全
#![allow(unused)]
fn main() {
fn safe_rust_ownership() {
// Move is destructive: original is gone
let data = vec![1, 2, 3];
let data2 = data; // Move happens
// data.len(); // Compile error: value used after move
// Borrowing: safe shared access
let owned = String::from("Hello, World!");
let slice: &str = &owned; // Borrow — no allocation
println!("{}", slice); // Always safe
// No dangling references possible
/*
let dangling_ref;
{
let temp = String::from("temporary");
dangling_ref = &temp; // Compile error: temp doesn't live long enough
}
*/
}
}
graph TD
A["Rust Ownership Safety<br/>Rust 所有权安全"] --> B["Destructive Moves<br/>破坏性移动"]
A --> C["Automatic Memory Management<br/>自动内存管理"]
A --> D["Compile-time Lifetime Checking<br/>编译期生命周期检查"]
A --> E["No Exceptions - Result Types<br/>没有异常,靠 Result 类型"]
B --> B1["Use-after-move is compile error<br/>移动后使用会直接编译失败"]
B --> B2["No zombie objects<br/>不会留下僵尸对象"]
C --> C1["Drop trait = RAII done right<br/>Drop trait 让 RAII 真正站住"]
C --> C2["No Rule of Five needed<br/>不用写 Rule of Five 套路"]
D --> D1["Borrow checker prevents dangling<br/>借用检查器阻止悬垂引用"]
D --> D2["References always valid<br/>引用始终保持有效"]
E --> E1["Result<T,E> - errors in types<br/>错误直接写进类型"]
E --> E2["? operator for propagation<br/>用 ? 传播错误"]
style A fill:#51cf66,color:#000
style B fill:#91e5a3,color:#000
style C fill:#91e5a3,color:#000
style D fill:#91e5a3,color:#000
style E fill:#91e5a3,color:#000
Memory Layout: Rust References
内存布局:Rust 引用
graph TD
RM1["Stack<br/>栈"] --> RP1["&i32 ref<br/>`&i32` 引用"]
RM2["Stack/Heap<br/>栈或堆"] --> RV1["i32 value = 42<br/>`i32` 值 = 42"]
RP1 -.->|"Safe reference - Lifetime checked<br/>安全引用,已做生命周期检查"| RV1
RM3["Borrow Checker<br/>借用检查器"] --> RC1["Prevents dangling refs at compile time<br/>在编译期阻止悬垂引用"]
style RC1 fill:#51cf66,color:#000
style RP1 fill:#91e5a3,color:#000
Box<T> Heap Allocation Visualization
Box<T> 堆分配示意
#![allow(unused)]
fn main() {
fn box_allocation_example() {
// Stack allocation
let stack_value = 42;
// Heap allocation with Box
let heap_value = Box::new(42);
// Moving ownership
let moved_box = heap_value;
// heap_value is no longer accessible
}
}
graph TD
subgraph "Stack Frame<br/>栈帧"
SV["stack_value: 42"]
BP["heap_value: Box<i32>"]
BP2["moved_box: Box<i32>"]
end
subgraph "Heap<br/>堆"
HV["42"]
end
BP -->|"Owns<br/>拥有"| HV
BP -.->|"Move ownership<br/>转移所有权"| BP2
BP2 -->|"Now owns<br/>现在拥有"| HV
subgraph "After Move<br/>移动之后"
BP_X["heap_value: MOVED<br/>heap_value:已移动"]
BP2_A["moved_box: Box<i32>"]
end
BP2_A -->|"Owns<br/>拥有"| HV
style BP_X fill:#ff6b6b,color:#000
style HV fill:#91e5a3,color:#000
style BP2_A fill:#51cf66,color:#000
Slice Operations Visualization
切片操作示意
#![allow(unused)]
fn main() {
fn slice_operations() {
let data = vec![1, 2, 3, 4, 5, 6, 7, 8];
let full_slice = &data[..]; // [1,2,3,4,5,6,7,8]
let partial_slice = &data[2..6]; // [3,4,5,6]
let from_start = &data[..4]; // [1,2,3,4]
let to_end = &data[3..]; // [4,5,6,7,8]
}
}
graph TD
V["Vec: [1, 2, 3, 4, 5, 6, 7, 8]"] --> FS["&data[..] -> all elements<br/>所有元素"]
V --> PS["&data[2..6] -> [3, 4, 5, 6]"]
V --> SS["&data[..4] -> [1, 2, 3, 4]"]
V --> ES["&data[3..] -> [4, 5, 6, 7, 8]"]
style V fill:#e3f2fd,color:#000
style FS fill:#91e5a3,color:#000
style PS fill:#91e5a3,color:#000
style SS fill:#91e5a3,color:#000
style ES fill:#91e5a3,color:#000
Other Rust USPs and features
Rust 其他明显优势
- No data races between threads because
Send/Syncare checked at compile time.
线程之间没有数据竞争,因为Send/Sync会在编译期被检查。 - No use-after-move, unlike C++
std::move, which can留下“被搬空但还能碰”的对象。
没有 use-after-move,这一点和 C++std::move形成鲜明对比。 - No uninitialized variables.
没有未初始化变量。- Every variable must be initialized before it is used.
所有变量都必须先初始化再使用。
- Every variable must be initialized before it is used.
- No trivial memory leaks.
不会出现那种轻轻松松就漏掉的内存泄漏。Droptrait gives proper RAII without Rule of Five ceremony.Droptrait 把 RAII 做顺了,不需要 Rule of Five 仪式感写法。- The compiler releases memory automatically when values go out of scope.
值离开作用域时,编译器会自动安排释放。
- No forgotten locks on mutexes.
不会忘记解互斥锁。- Lock guards are the only legal way to access the protected data.
锁守卫才是访问受保护数据的唯一正规入口。
- Lock guards are the only legal way to access the protected data.
- No exception-handling maze.
也没有异常处理迷宫。- Errors are values (
Result<T, E>) and are propagated with?.
错误就是值,通过Result<T, E>表达,再用?传播。
- Errors are values (
- Excellent support for type inference, enums, pattern matching, and zero-cost abstractions.
类型推断、枚举、模式匹配和零成本抽象都很能打。 - Built-in support for dependency management, building, testing, formatting, and linting.
依赖管理、构建、测试、格式化、lint 这一整套工具链都是自带的。cargoreplaces the usual make / CMake plus extra lint and test glue.cargo基本能替代 make / CMake 再加一堆零碎测试与检查工具。
Quick Reference: Rust vs C/C++
速查表:Rust 与 C / C++ 对照
| Concept 概念 | C | C++ | Rust | Key Difference 关键差别 |
|---|---|---|---|---|
| Memory management 内存管理 | malloc()/free() | unique_ptr, shared_ptr | Box<T>, Rc<T>, Arc<T> | Automatic, no cycles 自动管理,并尽量避开引用环问题 |
| Arrays 数组 | int arr[10] | std::vector<T>, std::array<T> | Vec<T>, [T; N] | Bounds checking by default 默认带边界检查 |
| Strings 字符串 | char* with \0 | std::string, string_view | String, &str | UTF-8 guaranteed, lifetime-checked UTF-8 默认保证,生命周期可检查 |
| References 引用 | int* ptr | T&, T&& | &T, &mut T | Borrow checking, lifetimes 借用检查加生命周期 |
| Polymorphism 多态 | Function pointers | Virtual functions, inheritance | Traits, trait objects | Composition over inheritance 更强调组合而不是继承 |
| Generic programming 泛型编程 | Macros (void*) | Templates | Generics + trait bounds | Better error messages 错误信息通常更友好 |
| Error handling 错误处理 | Return codes, errno | Exceptions, std::optional | Result<T, E>, Option<T> | No hidden control flow 没有隐藏控制流 |
| NULL / null safety 空值安全 | ptr == NULL | nullptr, std::optional<T> | Option<T> | Forced null checking 强制显式处理空值 |
| Thread safety 线程安全 | Manual (pthreads) | Manual synchronization | Compile-time guarantees | Data races impossible in safe Rust 安全 Rust 中数据竞争写不出来 |
| Build system 构建系统 | Make, CMake | CMake, Make, etc. | Cargo | Integrated toolchain 工具链一体化 |
| Undefined behavior 未定义行为 | Runtime crashes | Subtle UB (signed overflow, aliasing) | Compile-time errors | Safety guaranteed far earlier 更早把安全问题挡在编译阶段 |