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
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
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
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,
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
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.