diff --git a/src/doc/trpl/the-stack-and-the-heap.md b/src/doc/trpl/the-stack-and-the-heap.md index cfab268a7c5..e4317f9c399 100644 --- a/src/doc/trpl/the-stack-and-the-heap.md +++ b/src/doc/trpl/the-stack-and-the-heap.md @@ -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 | -|-----------------|------|----------------| -| 230 | | 5 | -| ... | ... | ... | -| 1 | y | 42 | -| 0 | x | 230 | +| Address | Name | Value | +|-----------------|------|------------------| +| 230 | | 5 | +| ... | ... | ... | +| 1 | y | 42 | +| 0 | x | → 230 | We have 230 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 | -|----------------------|------|----------------------| -| 230 | | 5 | -| (230) - 1 | | | -| (230) - 2 | | | -| (230) - 3 | | 42 | -| ... | ... | ... | -| 3 | y | (230) - 3 | -| 2 | y | 42 | -| 1 | y | 42 | -| 0 | x | 230 | +| Address | Name | Value | +|----------------------|------|------------------------| +| 230 | | 5 | +| (230) - 1 | | | +| (230) - 2 | | | +| (230) - 3 | | 42 | +| ... | ... | ... | +| 3 | y | → (230) - 3 | +| 2 | y | 42 | +| 1 | y | 42 | +| 0 | x | → 230 | In this case, we’ve allocated four things on the heap, but deallocated two of them. There’s a gap between 230 and (230) - 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 | -|-----------------|------|----------------| -| 230 | | 20 | -| ... | ... | ... | -| 2 | j | 0 | -| 1 | i | 230 | -| 0 | h | 3 | +| Address | Name | Value | +|-----------------|------|------------------| +| 230 | | 20 | +| ... | ... | ... | +| 2 | j | → 0 | +| 1 | i | → 230 | +| 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 | -|-----------------|------|----------------| -| 230 | | 20 | -| ... | ... | ... | -| 5 | z | 4 | -| 4 | y | 10 | -| 3 | x | 0 | -| 2 | j | 0 | -| 1 | i | 230 | -| 0 | h | 3 | +| Address | Name | Value | +|-----------------|------|-----------------| +| 230 | | 20 | +| ... | ... | ... | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → 230| +| 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 | -|-----------------|------|----------------| -| 230 | | 20 | -| ... | ... | ... | -| 7 | g | 100 | -| 6 | f | 4 | -| 5 | z | 4 | -| 4 | y | 10 | -| 3 | x | 0 | -| 2 | j | 0 | -| 1 | i | 230 | -| 0 | h | 3 | +| Address | Name | Value | +|-----------------|------|------------------| +| 230 | | 20 | +| ... | ... | ... | +| 7 | g | 100 | +| 6 | f | → 4 | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → 230 | +| 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 | -|-----------------|------|----------------| -| 230 | | 20 | -| ... | ... | ... | -| 5 | z | 4 | -| 4 | y | 10 | -| 3 | x | 0 | -| 2 | j | 0 | -| 1 | i | 230 | -| 0 | h | 3 | +| Address | Name | Value | +|-----------------|------|------------------| +| 230 | | 20 | +| ... | ... | ... | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → 230 | +| 0 | h | 3 | Next, `foo()` calls `bar()` with `x` and `z`: -| Address | Name | Value | -|----------------------|------|----------------------| -| 230 | | 20 | -| (230) - 1 | | 5 | -| ... | ... | ... | -| 10 | e | 9 | -| 9 | d | (230) - 1 | -| 8 | c | 5 | -| 7 | b | 4 | -| 6 | a | 0 | -| 5 | z | 4 | -| 4 | y | 10 | -| 3 | x | 0 | -| 2 | j | 0 | -| 1 | i | 230 | -| 0 | h | 3 | +| Address | Name | Value | +|----------------------|------|------------------------| +| 230 | | 20 | +| (230) - 1 | | 5 | +| ... | ... | ... | +| 10 | e | → 9 | +| 9 | d | → (230) - 1 | +| 8 | c | 5 | +| 7 | b | → 4 | +| 6 | a | → 0 | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → 230 | +| 0 | h | 3 | We end up allocating another value on the heap, and so we have to subtract one from 230. 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 | -|----------------------|------|----------------------| -| 230 | | 20 | -| (230) - 1 | | 5 | -| ... | ... | ... | -| 12 | g | 100 | -| 11 | f | 9 | -| 10 | e | 9 | -| 9 | d | (230) - 1 | -| 8 | c | 5 | -| 7 | b | 4 | -| 6 | a | 0 | -| 5 | z | 4 | -| 4 | y | 10 | -| 3 | x | 0 | -| 2 | j | 0 | -| 1 | i | 230 | -| 0 | h | 3 | +| Address | Name | Value | +|----------------------|------|------------------------| +| 230 | | 20 | +| (230) - 1 | | 5 | +| ... | ... | ... | +| 12 | g | 100 | +| 11 | f | → 9 | +| 10 | e | → 9 | +| 9 | d | → (230) - 1 | +| 8 | c | 5 | +| 7 | b | → 4 | +| 6 | a | → 0 | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → 230 | +| 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 | -|----------------------|------|----------------------| -| 230 | | 20 | -| (230) - 1 | | 5 | -| ... | ... | ... | -| 10 | e | 9 | -| 9 | d | (230) - 1 | -| 8 | c | 5 | -| 7 | b | 4 | -| 6 | a | 0 | -| 5 | z | 4 | -| 4 | y | 10 | -| 3 | x | 0 | -| 2 | j | 0 | -| 1 | i | 230 | -| 0 | h | 3 | +| Address | Name | Value | +|----------------------|------|------------------------| +| 230 | | 20 | +| (230) - 1 | | 5 | +| ... | ... | ... | +| 10 | e | → 9 | +| 9 | d | → (230) - 1 | +| 8 | c | 5 | +| 7 | b | → 4 | +| 6 | a | → 0 | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → 230 | +| 0 | h | 3 | Next, we return from `bar()`. `d` in this case is a `Box`, so it also frees what it points to: (230) - 1. -| Address | Name | Value | -|-----------------|------|----------------| -| 230 | | 20 | -| ... | ... | ... | -| 5 | z | 4 | -| 4 | y | 10 | -| 3 | x | 0 | -| 2 | j | 0 | -| 1 | i | 230 | -| 0 | h | 3 | +| Address | Name | Value | +|-----------------|------|------------------| +| 230 | | 20 | +| ... | ... | ... | +| 5 | z | → 4 | +| 4 | y | 10 | +| 3 | x | → 0 | +| 2 | j | → 0 | +| 1 | i | → 230 | +| 0 | h | 3 | And after that, `foo()` returns: -| Address | Name | Value | -|-----------------|------|----------------| -| 230 | | 20 | -| ... | ... | ... | -| 2 | j | 0 | -| 1 | i | 230 | -| 0 | h | 3 | +| Address | Name | Value | +|-----------------|------|------------------| +| 230 | | 20 | +| ... | ... | ... | +| 2 | j | → 0 | +| 1 | i | → 230 | +| 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.