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

Why does the Rust documentation say that sharing a reference to a vector would create an invalid vector even though the vector is on the heap?

以下摘自The Rust Programming Language chapter on ownership:

Now consider the following code fragment:

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

let mut v2 = v;

The first line allocates memory for the vector object v on the stack like it does for x above. But in addition to that it also allocates some memory on the heap for the actual data ([1, 2, 3]). Rust copies the address of this heap allocation to an internal pointer, which is part of the vector object placed on the stack (let's call it the data pointer).

It is worth pointing out (even at the risk of stating the obvious) that the vector object and its data live in separate memory regions instead of being a single contiguous memory allocation (due to reasons we will not go into at this point of time). These two parts of the vector (the one on the stack and one on the heap) must agree with each other at all times with regards to things like the length, capacity, etc.

When we move v to v2, Rust actually does a bitwise copy of the vector object v into the stack allocation represented by v2. This shallow copy does not create a copy of the heap allocation containing the actual data. Which means that there would be two pointers to the contents of the vector both pointing to the same memory allocation on the heap. It would violate Rust’s safety guarantees by introducing a data race if one could access both v and v2 at the same time.

For example if we truncated the vector to just two elements through v2:

v2.truncate(2);

and v were still accessible we'd end up with an invalid vector since v would not know that the heap data has been truncated. Now, the part of the vector v on the stack does not agree with the corresponding part on the heap. v still thinks there are three elements in the vector and will happily let us access the non existent element v[2] but as you might already know this is a recipe for disaster. Especially because it might lead to a segmentation fault or worse allow an unauthorized user to read from memory to which they don't have access.

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

and v were still accessible we'd end up with an invalid vector since v would not know that the heap data has been truncated

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

如果v2改变堆上的这个数据,v2的内部指针会更新为新的数据分配地址,而v1的内部指针仍然指向旧的数据分配地址!

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