1

以下是The Rust Programming Language 关于所有权一章的摘录:

现在考虑以下代码片段:

let v = vec![1, 2, 3];

let mut v2 = v;

第一行v像上面一样为堆栈上的向量对​​象分配内存x。但除此之外,它还在堆上为实际数据分配一些内存([1, 2, 3])。Rust 将此堆分配的地址复制到一个内部指针,该指针是放置在堆栈上的向量对​​象的一部分(我们称之为数据指针)。

值得指出(即使冒着说明显而易见的风险)向量对象及其数据存在于单独的内存区域中,而不是单个连续的内存分配(由于我们目前不会讨论的原因) . 向量的这两个部分(堆栈上的一个和堆上的一个)在长度、容量等方面必须始终相互一致。

当我们转到vv2,Rust 实际上将向量对象按位复制v到由 表示的堆栈分配中v2。这个浅拷贝不会创建包含实际数据的堆分配的副本。这意味着将有两个指向向量内容的指针,它们都指向堆上的相同内存分配。如果一个人可以同时访问两者v,就会通过引入数据竞争来违反 Rust 的安全保证v2

例如,如果我们通过以下方式将向量截断为两个元素 v2

v2.truncate(2);

并且v仍然可以访问,我们最终会得到一个无效的向量,因为v 不知道堆数据已被截断。现在,v堆栈上的向量部分与堆上的相应部分不一致。v仍然认为向量中有三个元素,并且很乐意让我们访问不存在的元素v[2],但是您可能已经知道这是灾难的根源。特别是因为它可能导致分段错误或更糟的是允许未经授权的用户从他们无权访问的内存中读取。

使用 截断向量后v2,将在堆内存上更新截断的值。v1仍然看到堆内存,截断后,它看到了新值。那为什么书上说

并且v仍然可以访问,我们最终会得到一个无效的向量,因为v不知道堆数据已被截断

4

2 回答 2

2

您缺少的是 aVec包含指向堆的指针和 alen或堆数据的长度。如果v2截断Vec,则可能截断的数据已被释放,并且v1仍然认为截断的内存仍然是向量的一部分。

于 2017-05-03T13:43:18.773 回答
1

我想我明白了。关键是要知道 Rust 有这个内部指针,它又是堆栈上的一个空间,Rust 使用它来定位堆上数据的地址!

如果v2更改堆上的这些数据,则v2' 的内部指针将更新为新的数据分配地址,而v1' 的内部指针仍将引用旧的数据分配地址!

于 2017-05-03T06:54:41.757 回答