]> git.lizzy.rs Git - rust.git/commitdiff
Explained the data race with an example.
authorSandeep Datta <datta.sandeep@gmail.com>
Thu, 11 Feb 2016 14:10:19 +0000 (19:40 +0530)
committerSandeep Datta <datta.sandeep@gmail.com>
Thu, 11 Feb 2016 14:10:19 +0000 (19:40 +0530)
src/doc/book/ownership.md

index 585e337ccc2e62d170bb089841b0c874db795980..5c603582bfc67521583a4ef22058e05a4a28c459 100644 (file)
@@ -122,7 +122,9 @@ special annotation here, it’s the default thing that Rust does.
 ## The details
 
 The reason that we cannot use a binding after we’ve moved it is subtle, but
-important. When we write code like this:
+important. 
+
+When we write code like this:
 
 ```rust
 let x = 10;
@@ -140,14 +142,18 @@ let v = vec![1, 2, 3];
 let v2 = v;
 ```
 
-The first line allocates memory for the vector object, `v`, on the stack like
+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 on the [heap][sh] for the actual data `[1, 2, 3]`. Rust copies the address
-of this heap allocation to an internal pointer 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 being redundant 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).
+on the [heap][sh] 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 repeating things) 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
@@ -155,8 +161,22 @@ 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. Therefore, Rust forbids using `v` after we’ve
-done the move (shallow copy).
+`v` and `v2` at the same time. 
+
+For example if we truncated the vector to just two elements through `v2`:
+
+```rust
+v2.truncate(2);
+```
+
+and `v1` were still accessible we'd end up with an invalid vector since it
+would not know that the heap data has been truncated. Now, the part of the
+vector `v1` on the stack does not agree with its corresponding part on the
+heap. `v1` still thinks there are three elements in the vector and will
+happily let us access the non existent element `v1[2]` but as you might
+already know this is a recipe for disaster.
+
+This is why Rust forbids using `v` after we’ve done the move.
 
 [sh]: the-stack-and-the-heap.html