认识安全和不安全

safe and unsafe

如果不用担心低级别的实现细节,那就太好了。谁会关心空元组占用了多少空间呢?可悲的是,它有时很重要,我们需要担心这个问题。开发人员开始关心实现细节的最常见的原因是性能,但更重要的是,当与硬件、操作系统或其他语言直接对接时,这些细节会成为正确性的问题。

当实现细节在安全的编程语言中开始变得重要时,程序员通常有三种选择。

  • 摆弄代码以鼓励编译器/运行时进行优化
  • 采用一种更不规范或更繁琐的设计来获得所需的实现
  • 用一种能让你处理这些细节的语言重写实现

对于最后一种选择,程序员往往使用的语言是C。这对于与那些只声明有 C 语言接口的系统对接来说往往是必要的。

不幸的是,C 语言使用起来非常不安全(尽管有时有很好的理由),当试图与另一种语言互操作时,这种不安全感会被放大。必须小心翼翼地确保 C 语言和其他语言对正在发生的事情达成一致,并且他们不会踩到对方的脚趾。

那么,这与 Rust 有什么关系呢?

嗯,与 C 不同,Rust 是一种安全的编程语言。

但是,和 C 语言一样,Rust 也是一种不安全的编程语言。

更准确地说,Rust 同时包含了一种安全和一种不安全的编程语言。

Rust 可以被认为是两种编程语言的结合。安全的 Rust不安全的 Rust。顾名思义,安全的 Rust 是安全的。不安全的 Rust 是,嗯,不安全的。事实上,不安全的 Rust 让我们做一些真正不安全的事情。Rust 的作者会恳求你不要做这些事情,但我们还是要做。

安全 Rust 是真正的 Rust 编程语言。如果你只写 Safe Rust,你将永远不必担心类型安全或内存安全的问题。你永远不会忍受悬空的指针,释放后使用(use-after-free),或任何其他类型的未定义行为。

标准库也为你提供了足够多的开箱即用的工具,你将能够用纯粹的安全 Rust 编写高性能的应用程序和库。

但是,也许你想和另一种语言对话,也许你正在写一个标准库没有暴露的低级抽象,也许你正在标准库(它完全是用 Rust 写的),也许你需要做一些类型系统不理解的事情,或者也许不只是愣头青。也许你需要不安全的 Rust。

不安全的 Rust 与安全的 Rust 完全一样,具有所有相同的规则和语义。它只是让你做一些额外的、绝对不安全的事情(我们将在下一节中定义)。

这种分离的价值在于,我们获得了使用像 C 这样的不安全语言的好处——对实现细节的低层次控制——而没有试图将其与完全不同的安全语言整合的大部分问题。

仍然有一些问题——最明显的是,我们必须意识到类型系统所假设的属性,并在任何与不安全的 Rust 交互的代码中审核它们。这就是本书的目的:教你了解这些假设以及如何管理它们。