memory-management - Rust 如何保证内存安全并防止段错误?

标签 memory-management segmentation-fault rust

我一直在寻找一种语言来学习,我看到 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/

相关文章:

javascript - node.removeChild(node.firstChild) 是否会造成内存泄漏?

Java,将对象转换为软引用

c++ - Valgrind 报告在一个系统上读取无效,但在另一个系统上没有

c++ - 将 ROS PointCloud2 消息转换为 PCL PointCloud 后出现奇怪的段错误

serialization - 将字符串或枚举放入 LMDB

具有由实现定义的常量字段的 Rust 特征

c++ - 为大型本地数据处理扩展堆栈大小是个好主意吗?

ios - 检测 UITableViewCells 何时完全完成

c - 调用 fgets 从文件中读取行时出现段错误

rust - 从拥有的资源中归还借用