从内存管理策略看Rust独特性 - Khorchanov


我是一名 Java 开发人员,我知道在开发关键的安全应用程序时使用这种语言的主要优点和缺点。每个人接近 Java 的主要内容是它的 GC(又名垃圾收集器)。最早提出开箱即用的自动内存管理的语言是它。还有许多其他语言使用 GC、Javascript、Golang、python……
在 Rust 之前,语言只有两种策略来处理内存管理。但现在我们有三个。
 
1. 让开发人员手工处理内存分配和释放
从历史上看,这是第一种方法。C 就是一个很好的例子。有了 malloc 和 free 两个过程,开发者可以计算出自己需要的内存,手动分配,不需要的时候再释放。为开发人员提供此功能并不是免费的,在具有复杂代码库的大型应用程序中,任何人都可以:

  • 为所需数据分配错误大小
  • 忘记在应该释放内存的时候
  • 释放内存,引入另一种称为悬空指针的问题,从而访问坏内存导致安全问题。

但是,在高性能是关键的许多情况下,赋予开发人员手动处理内存的能力有时是完美的,例如实时应用程序,因为我们为 GC 算法消除了相当多的运行时执行时间以自动释放未使用的内存(GC 带有暂停......) .
 
2. 自动内存管理
背后的想法是让开发人员创建逻辑并让另一个系统处理内存分配和释放。这提高了此类程序的安全性,不再是:指针操作、手动内存分配、悬空指针、访问错误内存地址……我们可以构建不易出错的系统,开发人员最终可以专注于核心功能而不是技术指针算术。

这个系统被称为垃圾收集器,它是为了解决上述问题而出现的。但很快就会带来各种性能下降,Java 的 VM 会暂停。然后我们有许多实现随着时间的推移逐渐提高性能。Java 17 中的shenandoah是高性能 GC 的最佳示例。
 
3. Rust 模式:混合
 rust 提出了另一种方法:我们可以自动管理内存,但同时避免让观察者增加运行时的开销吗?是的,Rust 编译器。在编译时,它会计算空闲内存的放置位置,命名为drop函数,并将其放置在源代码中应位于的位置,所有这些都在编译之前。这要归功于借用检查器
变量由拥有它的“上下文”实现管理,并且随着时间的推移,变量的所有权可以可从“上下文”转移或借用给另一个“上下文”,一旦变量的所有者不在范围内,变量的最后一个所有者负责释放其内存。
Rust 解决了另一个问题,使用切片悬挂指针,通过将所有变量设置为默认的不可变状态来实现并发。