mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Auto merge of #27595 - mike-marcacci:patch-1, r=steveklabnik
Keeping integer values and integer references in the "value" columns made the examples quite difficult for me to follow. I've added unicode arrows to references to make them more obvious, without using any characters with actual meaning in the rust language (like `&` or previously `~`). r? @steveklabnik
This commit is contained in:
commit
cbf4c342cf
@ -217,12 +217,12 @@ on the heap. The actual value of the box is a structure which has a pointer to
|
||||
it allocates some memory for the heap, and puts `5` there. The memory now looks
|
||||
like this:
|
||||
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|----------------|
|
||||
| 2<sup>30</sup> | | 5 |
|
||||
| ... | ... | ... |
|
||||
| 1 | y | 42 |
|
||||
| 0 | x | 2<sup>30</sup> |
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|------------------|
|
||||
| 2<sup>30</sup> | | 5 |
|
||||
| ... | ... | ... |
|
||||
| 1 | y | 42 |
|
||||
| 0 | x | → 2<sup>30</sup> |
|
||||
|
||||
We have 2<sup>30</sup> in our hypothetical computer with 1GB of RAM. And since
|
||||
our stack grows from zero, the easiest place to allocate memory is from the
|
||||
@ -242,17 +242,17 @@ freed in any order, it can end up with ‘holes’. Here’s a diagram of the me
|
||||
layout of a program which has been running for a while now:
|
||||
|
||||
|
||||
| Address | Name | Value |
|
||||
|----------------------|------|----------------------|
|
||||
| 2<sup>30</sup> | | 5 |
|
||||
| (2<sup>30</sup>) - 1 | | |
|
||||
| (2<sup>30</sup>) - 2 | | |
|
||||
| (2<sup>30</sup>) - 3 | | 42 |
|
||||
| ... | ... | ... |
|
||||
| 3 | y | (2<sup>30</sup>) - 3 |
|
||||
| 2 | y | 42 |
|
||||
| 1 | y | 42 |
|
||||
| 0 | x | 2<sup>30</sup> |
|
||||
| Address | Name | Value |
|
||||
|----------------------|------|------------------------|
|
||||
| 2<sup>30</sup> | | 5 |
|
||||
| (2<sup>30</sup>) - 1 | | |
|
||||
| (2<sup>30</sup>) - 2 | | |
|
||||
| (2<sup>30</sup>) - 3 | | 42 |
|
||||
| ... | ... | ... |
|
||||
| 3 | y | → (2<sup>30</sup>) - 3 |
|
||||
| 2 | y | 42 |
|
||||
| 1 | y | 42 |
|
||||
| 0 | x | → 2<sup>30</sup> |
|
||||
|
||||
In this case, we’ve allocated four things on the heap, but deallocated two of
|
||||
them. There’s a gap between 2<sup>30</sup> and (2<sup>30</sup>) - 3 which isn’t
|
||||
@ -304,22 +304,22 @@ fn main() {
|
||||
|
||||
When we enter `main()`, memory looks like this:
|
||||
|
||||
| Address | Name | Value |
|
||||
|---------|------|-------|
|
||||
| 1 | y | 0 |
|
||||
| 0 | x | 5 |
|
||||
| Address | Name | Value |
|
||||
|---------|------|--------|
|
||||
| 1 | y | → 0 |
|
||||
| 0 | x | 5 |
|
||||
|
||||
`x` is a plain old `5`, and `y` is a reference to `x`. So its value is the
|
||||
memory location that `x` lives at, which in this case is `0`.
|
||||
|
||||
What about when we call `foo()`, passing `y` as an argument?
|
||||
|
||||
| Address | Name | Value |
|
||||
|---------|------|-------|
|
||||
| 3 | z | 42 |
|
||||
| 2 | i | 0 |
|
||||
| 1 | y | 0 |
|
||||
| 0 | x | 5 |
|
||||
| Address | Name | Value |
|
||||
|---------|------|--------|
|
||||
| 3 | z | 42 |
|
||||
| 2 | i | → 0 |
|
||||
| 1 | y | → 0 |
|
||||
| 0 | x | 5 |
|
||||
|
||||
Stack frames aren’t just for local bindings, they’re for arguments too. So in
|
||||
this case, we need to have both `i`, our argument, and `z`, our local variable
|
||||
@ -366,29 +366,29 @@ fn main() {
|
||||
|
||||
First, we call `main()`:
|
||||
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|----------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 2 | j | 0 |
|
||||
| 1 | i | 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 2 | j | → 0 |
|
||||
| 1 | i | → 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
|
||||
We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
|
||||
value pointing there.
|
||||
|
||||
Next, at the end of `main()`, `foo()` gets called:
|
||||
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|----------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 5 | z | 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | 0 |
|
||||
| 2 | j | 0 |
|
||||
| 1 | i | 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|-----------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 5 | z | → 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | → 0 |
|
||||
| 2 | j | → 0 |
|
||||
| 1 | i | → 2<sup>30</sup>|
|
||||
| 0 | h | 3 |
|
||||
|
||||
Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value
|
||||
as `j`, since that’s what we passed it in. It’s a pointer to the `0` address,
|
||||
@ -396,51 +396,51 @@ since `j` points at `h`.
|
||||
|
||||
Next, `foo()` calls `baz()`, passing `z`:
|
||||
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|----------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 7 | g | 100 |
|
||||
| 6 | f | 4 |
|
||||
| 5 | z | 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | 0 |
|
||||
| 2 | j | 0 |
|
||||
| 1 | i | 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 7 | g | 100 |
|
||||
| 6 | f | → 4 |
|
||||
| 5 | z | → 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | → 0 |
|
||||
| 2 | j | → 0 |
|
||||
| 1 | i | → 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
|
||||
We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s
|
||||
over, we get rid of its stack frame:
|
||||
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|----------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 5 | z | 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | 0 |
|
||||
| 2 | j | 0 |
|
||||
| 1 | i | 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 5 | z | → 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | → 0 |
|
||||
| 2 | j | → 0 |
|
||||
| 1 | i | → 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
|
||||
Next, `foo()` calls `bar()` with `x` and `z`:
|
||||
|
||||
| Address | Name | Value |
|
||||
|----------------------|------|----------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| (2<sup>30</sup>) - 1 | | 5 |
|
||||
| ... | ... | ... |
|
||||
| 10 | e | 9 |
|
||||
| 9 | d | (2<sup>30</sup>) - 1 |
|
||||
| 8 | c | 5 |
|
||||
| 7 | b | 4 |
|
||||
| 6 | a | 0 |
|
||||
| 5 | z | 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | 0 |
|
||||
| 2 | j | 0 |
|
||||
| 1 | i | 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
| Address | Name | Value |
|
||||
|----------------------|------|------------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| (2<sup>30</sup>) - 1 | | 5 |
|
||||
| ... | ... | ... |
|
||||
| 10 | e | → 9 |
|
||||
| 9 | d | → (2<sup>30</sup>) - 1 |
|
||||
| 8 | c | 5 |
|
||||
| 7 | b | → 4 |
|
||||
| 6 | a | → 0 |
|
||||
| 5 | z | → 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | → 0 |
|
||||
| 2 | j | → 0 |
|
||||
| 1 | i | → 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
|
||||
We end up allocating another value on the heap, and so we have to subtract one
|
||||
from 2<sup>30</sup>. It’s easier to just write that than `1,073,741,823`. In any
|
||||
@ -448,70 +448,70 @@ case, we set up the variables as usual.
|
||||
|
||||
At the end of `bar()`, it calls `baz()`:
|
||||
|
||||
| Address | Name | Value |
|
||||
|----------------------|------|----------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| (2<sup>30</sup>) - 1 | | 5 |
|
||||
| ... | ... | ... |
|
||||
| 12 | g | 100 |
|
||||
| 11 | f | 9 |
|
||||
| 10 | e | 9 |
|
||||
| 9 | d | (2<sup>30</sup>) - 1 |
|
||||
| 8 | c | 5 |
|
||||
| 7 | b | 4 |
|
||||
| 6 | a | 0 |
|
||||
| 5 | z | 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | 0 |
|
||||
| 2 | j | 0 |
|
||||
| 1 | i | 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
| Address | Name | Value |
|
||||
|----------------------|------|------------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| (2<sup>30</sup>) - 1 | | 5 |
|
||||
| ... | ... | ... |
|
||||
| 12 | g | 100 |
|
||||
| 11 | f | → 9 |
|
||||
| 10 | e | → 9 |
|
||||
| 9 | d | → (2<sup>30</sup>) - 1 |
|
||||
| 8 | c | 5 |
|
||||
| 7 | b | → 4 |
|
||||
| 6 | a | → 0 |
|
||||
| 5 | z | → 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | → 0 |
|
||||
| 2 | j | → 0 |
|
||||
| 1 | i | → 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
|
||||
With this, we’re at our deepest point! Whew! Congrats for following along this
|
||||
far.
|
||||
|
||||
After `baz()` is over, we get rid of `f` and `g`:
|
||||
|
||||
| Address | Name | Value |
|
||||
|----------------------|------|----------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| (2<sup>30</sup>) - 1 | | 5 |
|
||||
| ... | ... | ... |
|
||||
| 10 | e | 9 |
|
||||
| 9 | d | (2<sup>30</sup>) - 1 |
|
||||
| 8 | c | 5 |
|
||||
| 7 | b | 4 |
|
||||
| 6 | a | 0 |
|
||||
| 5 | z | 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | 0 |
|
||||
| 2 | j | 0 |
|
||||
| 1 | i | 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
| Address | Name | Value |
|
||||
|----------------------|------|------------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| (2<sup>30</sup>) - 1 | | 5 |
|
||||
| ... | ... | ... |
|
||||
| 10 | e | → 9 |
|
||||
| 9 | d | → (2<sup>30</sup>) - 1 |
|
||||
| 8 | c | 5 |
|
||||
| 7 | b | → 4 |
|
||||
| 6 | a | → 0 |
|
||||
| 5 | z | → 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | → 0 |
|
||||
| 2 | j | → 0 |
|
||||
| 1 | i | → 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
|
||||
Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees
|
||||
what it points to: (2<sup>30</sup>) - 1.
|
||||
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|----------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 5 | z | 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | 0 |
|
||||
| 2 | j | 0 |
|
||||
| 1 | i | 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 5 | z | → 4 |
|
||||
| 4 | y | 10 |
|
||||
| 3 | x | → 0 |
|
||||
| 2 | j | → 0 |
|
||||
| 1 | i | → 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
|
||||
And after that, `foo()` returns:
|
||||
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|----------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 2 | j | 0 |
|
||||
| 1 | i | 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
| Address | Name | Value |
|
||||
|-----------------|------|------------------|
|
||||
| 2<sup>30</sup> | | 20 |
|
||||
| ... | ... | ... |
|
||||
| 2 | j | → 0 |
|
||||
| 1 | i | → 2<sup>30</sup> |
|
||||
| 0 | h | 3 |
|
||||
|
||||
And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
|
||||
it will clean up the last of the heap too.
|
||||
|
Loading…
Reference in New Issue
Block a user