Rust系统编程之内存模型

1.所有权(owenership)

1.1 规则

  • Rust 中的每一个值都有一个所有者owner
  • 值在任一时刻有且只有一个所有者
  • 当所有者(变量)离开作用域,这个值将被丢弃(销毁)

1.1 解释

Rust中每一个复杂类型都被一个unique_ptr包裹,如下图所示:

unique_ptr结构

这使得在这个对象离开作用域的时候会自动调用drop函数来销毁,满足RAII思想。

对于默认的赋值操作,全部发生的是移动语义,如下代码:

1
2
let a = "hello World".to_string();
let b = a; // 此时将a移动到b

上面操作本质上是将在栈上的智能指针对象进行值拷贝,然后在编译器语法层面控制变量a不可用,汇编代码如下:

rust移动语义

此时String对象的所有者从a转到了b,最终在局部变量离开作用域时调用drop函数进行销毁。

drop销毁

1.3 指定深拷贝

1
2
let a = "hello World".to_string();
let b = a.clone(); // 此时深拷贝a的数据,a继续有效

相关汇编实现如下:

clone函数实现

上述规则适用于一切赋值,包括参数传递和返回值。

2.引用

2.1 不可变引用

1
2
let a = "hello World".to_string();
let b = &a;

汇编代码如下:

引用实现

b中仅仅保存了一份a智能指针对象在栈上的地址。

2.2 可变引用

1
2
let mut a = "hello World".to_string();
let b = &mut a;

可变与不可变只在编译器语法层面区分,在汇编中一致。

2.3 互斥性

只能出现以下两种情况之一:

  • 一个可变引用,0个不可变引用
  • 0个可变引用,若干个不可变引用

2.内存模型

2.1 对象控制权转移

a.赋值

1
2
let a = "hello".to_string();
a = "world".to_string();

此时的内存模型如下:

赋值内存模型

此时存在栈上的智能指针对象a已经用于管理另外一块内存,而原来的内存在此时应该被释放。

b.拷贝

1
2
let a = "hello".to_string();
let b = a;

此时的内存模型如下:

拷贝内存模型

此时存在于栈上的智能指针b用于管理a的资源,a必须放弃管理,否则在退出时会造成double free。


Rust系统编程之内存模型
http://helloymf.github.io/2023/04/10/rust-xi-tong-bian-cheng-zhi-nei-cun-mo-xing/
作者
JNZ
许可协议