为什么Rust文档说即使向量在堆上,共享对向量的引用也会创建无效向量?

时间:2017-05-03 06:50:58

标签: rust memory-safety

以下是 The Rust Programming Language chapter on ownership的摘录:

  

现在考虑以下代码片段:

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

let mut v2 = v;
     

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

     

值得指出(即使有说明显而易见的风险)   向量对象及其数据存在于不同的内存区域中   而不是单个连续的内存分配(由于原因   我们不会在这个时间点进入)。这两部分   vector(堆栈中的一个和堆上的一个)必须同意每个   其他在任何时候都有关于长度,容量,   等

     

当我们将v移动到v2时,Rust实际上会执行向量的按位复制   将对象v放入由v2表示的堆栈分配中。这很浅   copy不会创建包含的堆分配的副本   实际数据。这意味着会有两个指针   向量的内容都指向相同的内存分配   堆。它会违反Rust的安全保障,引入一个   数据争用,如果可以同时访问vv2

     

例如,如果我们将向量截断为仅两个元素   v2

v2.truncate(2);
     

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

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

  

v仍然可访问我们最终会出现无效的向量,因为v不知道堆数据已被截断

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

如果v2在堆上更改了这些数据,v2的内部指针会使用新的数据分配地址进行更新,而v1的内部指针仍然会引用旧的数据分配地址!