我一直在寻找一种语言来学习,我看到 Rust 变得非常流行。
关于 Rust,内存安全和防止段错误有两件事给我留下了深刻的印象。
Rust 是如何做到这一点的?例如,Rust 和 Java 之间的哪些差异启用了 Rust 的安全功能?
最佳答案
Rust 如何实现内存安全的核心实际上非常简单。它主要取决于两个原则:所有权和借用。
所有权
编译器使用仿射类型系统来跟踪每个值的所有权:一个值最多只能使用一次,之后编译器将拒绝再次使用它。
fn main() {
let original = "Hello, World!".to_string();
let other = original;
println!("{}", original);
}
产生错误:
error[E0382]: use of moved value: `original`
--> src/main.rs:4:20
|
3 | let other = original;
| ----- value moved here
4 | println!("{}", original);
| ^^^^^^^^ value used here after move
|
= note: move occurs because `original` has type `std::string::String`, which does not implement the `Copy` trait
值得注意的是,这可以防止在 C 或 C++(智能指针之前)中经常遇到的可怕的双重释放。
借用
来自 Rust 的启发是,当混合使用别名和可变性时,就会出现内存问题:也就是说,当可以通过多个路径访问一 block 内存时,它会发生变异(或移走),留下悬空指针。
因此,借用检查的核心原则是:可变性异或别名。从原理上讲,它类似于读写锁。
这意味着 Rust 编译器跟踪别名 信息,为此它使用生命周期注解(那些 'a
在 & 'a var
) 将引用的生命周期和它们引用的值连接在一起。
如果有人引用或引用一个值(例如,引用struct
的字段或集合的元素),则该值被借用。借来的值不能移动。
可变性(无别名)
您在任何时候都只能获取对给定值的单个可变引用 (&mut T
),而没有不可变引用值(value)可能同时存在;它保证您可以独占访问这段内存,因此您可以安全地改变它。
别名(无可变性)
您可以随时获取对给定值的多个不可变引用 (&T
)。但是,您不能通过这些引用 (*) 改变任何内容。
(*) 我在撒谎;有像 RefCell
这样的结构实现了“内部可变性”;他们确实尊重可变性 XOR 别名原则,但将检查推迟到运行时。
就这样了?
差不多了 ;)
对于编译器编写者来说实现起来已经相当复杂,并且可能会过度限制用户(一些安全的程序无法使用该系统证明是安全的,需要跳过箍),但是核心原则确实是就这么简单。
那还剩下什么?
边界检查。这不是火箭科学,但可能会导致性能下降。大多数语言都对它有一定程度的支持,C 是个大异常(exception),而 C++ 对它有一些支持,尽管它是可选的。
关于memory-management - Rust 如何保证内存安全并防止段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36136201/