认识安全与非安全
如果不必担心底层实现细节,那就太好了。谁会在乎空元组占用多少空间呢?可惜,有时它确实重要,我们需要为此操心。开发者开始关心实现细节最常见的原因是性能,但更重要的是,在直接与硬件、操作系统或其他语言交互时,这些细节会影响程序的正确性。
当在一种安全编程语言中,实现细节开始变得重要时,程序员通常有三个选择:
- 修改代码以促使编译器/运行时执行优化
- 采用一种更非惯用或更繁琐的设计以获得期望的实现
- 用一种允许你处理这些细节的语言重写实现
对于最后一个选择,程序员倾向于使用的语言是 C。这通常是与只声明 C 接口的系统进行交互所必需的。
不幸的是,C 语言使用起来非常不安全(有时是出于充分的理由),而且当试图与另一种语言互操作时,这种不安全性会被放大。必须小心确保 C 语言和另一种语言在正在发生的事情上达成一致,并且它们互不干扰。
那么,这和 Rust 有什么关系呢?
嗯,与 C 不同的是,Rust 是一种安全编程语言。
但是,与 C 一样,Rust 是一种非安全编程语言。
更准确地说,Rust 包含 了一种安全编程语言和一种非安全编程语言。
Rust 可以被视为两种编程语言的结合体:安全 Rust 和 非安全 Rust。很恰当地,这些名字的意思完全符合其字面含义:安全 Rust 是安全的。非安全 Rust 则不然。实际上,非安全 Rust 允许我们做一些非常不安全的事情。那些 Rust 作者会恳求你不要做,但我们无论如何都会做的事情。
安全 Rust 是真正的 Rust 编程语言。如果你只编写安全 Rust,你将永远不必担心类型安全或内存安全。你永远不会遇到悬垂指针、use-after-free 或任何其他形式的未定义行为(简称 UB)。
标准库也提供了足够的开箱即用的工具,使你能够用纯粹的惯用安全 Rust 编写高性能应用程序和库。
但是也许你想与另一种语言交互。也许你正在编写一个标准库没有暴露的低层抽象。也许你正在编写标准库(标准库完全是用 Rust 写的)。也许你需要做一些类型系统不理解的事情,只是想捣鼓一些位。也许你需要非安全 Rust。
非安全 Rust 与安全 Rust 完全一样,具有所有相同的规则和语义。它只是允许你做一些额外的、明确不安全的事情(我们将在下一节中定义)。
这种分离的价值在于,我们获得了使用 C 这样不安全语言的好处——对实现细节的低层控制——同时避免了尝试将其与完全不同的安全语言集成所带来的大多数问题。
仍然存在一些问题——最值得注意的是,我们必须了解类型系统所假定的属性,并审查任何与非安全 Rust 交互的代码中的这些属性。这就是本书的目的:教你了解这些假定以及如何管理它们。