首页 文章

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

提问于
浏览
0

以下是Rust编程语言chapter on ownership的摘录:

现在考虑以下代码片段:let v = vec![1,2,3];

让mut v2 = v;
第一行为堆栈上的矢量对象v分配内存,就像上面的x一样 . 但除此之外,它还在堆上为实际数据分配了一些内存([1,2,3]) . Rust将此堆分配的地址复制到内部指针,该指针是放置在堆栈上的向量对象的一部分(让我们将其称为数据指针) . 值得指出的是(即使存在明显的风险)向量对象及其数据存在于单独的内存区域而不是单个连续的内存分配(由于我们此时不会进入的原因) . 向量的这两部分(堆栈中的一个和堆上的一个)必须始终在长度,容量等方面相互一致 . 当我们将v移动到v2时,Rust实际上是按位进行的向量对象v的副本到由v2表示的堆栈分配中 . 此浅拷贝不会创建包含实际数据的堆分配的副本 . 这意味着将有两个指向向量内容的指针,这两个指针都指向堆上的相同内存分配 . 如果可以同时访问v和v2,则会引入数据竞争,从而违反Rust的安全保障 . 例如,如果我们通过v2将向量截断为仅两个元素:v2.truncate(2);
和v仍然可访问我们最终得到一个无效的向量,因为v不知道堆数据已被截断 . 现在,堆栈上的向量v的一部分与堆上的相应部分不一致 . v仍然认为向量中有三个元素,并且很乐意让我们访问不存在的元素v [2]但是你可能已经知道这是一个灾难的秘诀 . 特别是因为它可能导致分段错误或更糟糕地允许未经授权的用户从他们无法访问的内存中读取 .

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

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

2 回答

  • 0

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

  • 1

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

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

相关问题