Rollup merge of #28466 - baskerville:trpl-heap-highest-addr, r=steveklabnik
r? @steveklabnik
This commit is contained in:
commit
36190ef91d
1 changed files with 84 additions and 84 deletions
|
@ -217,18 +217,18 @@ 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
|
it allocates some memory for the heap, and puts `5` there. The memory now looks
|
||||||
like this:
|
like this:
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|-----------------|------|------------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 5 |
|
| (2<sup>30</sup>) - 1 | | 5 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 1 | y | 42 |
|
| 1 | y | 42 |
|
||||||
| 0 | x | → 2<sup>30</sup> |
|
| 0 | x | → (2<sup>30</sup>) - 1 |
|
||||||
|
|
||||||
We have 2<sup>30</sup> in our hypothetical computer with 1GB of RAM. And since
|
We have (2<sup>30</sup>) - 1 in our hypothetical computer with 1GB of RAM. And since
|
||||||
our stack grows from zero, the easiest place to allocate memory is from the
|
our stack grows from zero, the easiest place to allocate memory is from the
|
||||||
other end. So our first value is at the highest place in memory. And the value
|
other end. So our first value is at the highest place in memory. And the value
|
||||||
of the struct at `x` has a [raw pointer][rawpointer] to the place we’ve
|
of the struct at `x` has a [raw pointer][rawpointer] to the place we’ve
|
||||||
allocated on the heap, so the value of `x` is 2<sup>30</sup>, the memory
|
allocated on the heap, so the value of `x` is (2<sup>30</sup>) - 1, the memory
|
||||||
location we’ve asked for.
|
location we’ve asked for.
|
||||||
|
|
||||||
[rawpointer]: raw-pointers.html
|
[rawpointer]: raw-pointers.html
|
||||||
|
@ -244,18 +244,18 @@ layout of a program which has been running for a while now:
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|----------------------|------|------------------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 5 |
|
| (2<sup>30</sup>) - 1 | | 5 |
|
||||||
| (2<sup>30</sup>) - 1 | | |
|
|
||||||
| (2<sup>30</sup>) - 2 | | |
|
| (2<sup>30</sup>) - 2 | | |
|
||||||
| (2<sup>30</sup>) - 3 | | 42 |
|
| (2<sup>30</sup>) - 3 | | |
|
||||||
|
| (2<sup>30</sup>) - 4 | | 42 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 3 | y | → (2<sup>30</sup>) - 3 |
|
| 3 | y | → (2<sup>30</sup>) - 4 |
|
||||||
| 2 | y | 42 |
|
| 2 | y | 42 |
|
||||||
| 1 | y | 42 |
|
| 1 | y | 42 |
|
||||||
| 0 | x | → 2<sup>30</sup> |
|
| 0 | x | → (2<sup>30</sup>) - 1 |
|
||||||
|
|
||||||
In this case, we’ve allocated four things on the heap, but deallocated two of
|
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
|
them. There’s a gap between (2<sup>30</sup>) - 1 and (2<sup>30</sup>) - 4 which isn’t
|
||||||
currently being used. The specific details of how and why this happens depends
|
currently being used. The specific details of how and why this happens depends
|
||||||
on what kind of strategy you use to manage the heap. Different programs can use
|
on what kind of strategy you use to manage the heap. Different programs can use
|
||||||
different ‘memory allocators’, which are libraries that manage this for you.
|
different ‘memory allocators’, which are libraries that manage this for you.
|
||||||
|
@ -366,29 +366,29 @@ fn main() {
|
||||||
|
|
||||||
First, we call `main()`:
|
First, we call `main()`:
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|-----------------|------|------------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 20 |
|
| (2<sup>30</sup>) - 1 | | 20 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 2 | j | → 0 |
|
| 2 | j | → 0 |
|
||||||
| 1 | i | → 2<sup>30</sup> |
|
| 1 | i | → (2<sup>30</sup>) - 1 |
|
||||||
| 0 | h | 3 |
|
| 0 | h | 3 |
|
||||||
|
|
||||||
We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
|
We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
|
||||||
value pointing there.
|
value pointing there.
|
||||||
|
|
||||||
Next, at the end of `main()`, `foo()` gets called:
|
Next, at the end of `main()`, `foo()` gets called:
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|-----------------|------|-----------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 20 |
|
| (2<sup>30</sup>) - 1 | | 20 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 5 | z | → 4 |
|
| 5 | z | → 4 |
|
||||||
| 4 | y | 10 |
|
| 4 | y | 10 |
|
||||||
| 3 | x | → 0 |
|
| 3 | x | → 0 |
|
||||||
| 2 | j | → 0 |
|
| 2 | j | → 0 |
|
||||||
| 1 | i | → 2<sup>30</sup>|
|
| 1 | i | → (2<sup>30</sup>) - 1 |
|
||||||
| 0 | h | 3 |
|
| 0 | h | 3 |
|
||||||
|
|
||||||
Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value
|
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,
|
as `j`, since that’s what we passed it in. It’s a pointer to the `0` address,
|
||||||
|
@ -396,42 +396,42 @@ since `j` points at `h`.
|
||||||
|
|
||||||
Next, `foo()` calls `baz()`, passing `z`:
|
Next, `foo()` calls `baz()`, passing `z`:
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|-----------------|------|------------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 20 |
|
| (2<sup>30</sup>) - 1 | | 20 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 7 | g | 100 |
|
| 7 | g | 100 |
|
||||||
| 6 | f | → 4 |
|
| 6 | f | → 4 |
|
||||||
| 5 | z | → 4 |
|
| 5 | z | → 4 |
|
||||||
| 4 | y | 10 |
|
| 4 | y | 10 |
|
||||||
| 3 | x | → 0 |
|
| 3 | x | → 0 |
|
||||||
| 2 | j | → 0 |
|
| 2 | j | → 0 |
|
||||||
| 1 | i | → 2<sup>30</sup> |
|
| 1 | i | → (2<sup>30</sup>) - 1 |
|
||||||
| 0 | h | 3 |
|
| 0 | h | 3 |
|
||||||
|
|
||||||
We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s
|
We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s
|
||||||
over, we get rid of its stack frame:
|
over, we get rid of its stack frame:
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|-----------------|------|------------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 20 |
|
| (2<sup>30</sup>) - 1 | | 20 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 5 | z | → 4 |
|
| 5 | z | → 4 |
|
||||||
| 4 | y | 10 |
|
| 4 | y | 10 |
|
||||||
| 3 | x | → 0 |
|
| 3 | x | → 0 |
|
||||||
| 2 | j | → 0 |
|
| 2 | j | → 0 |
|
||||||
| 1 | i | → 2<sup>30</sup> |
|
| 1 | i | → (2<sup>30</sup>) - 1 |
|
||||||
| 0 | h | 3 |
|
| 0 | h | 3 |
|
||||||
|
|
||||||
Next, `foo()` calls `bar()` with `x` and `z`:
|
Next, `foo()` calls `bar()` with `x` and `z`:
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|----------------------|------|------------------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 20 |
|
| (2<sup>30</sup>) - 1 | | 20 |
|
||||||
| (2<sup>30</sup>) - 1 | | 5 |
|
| (2<sup>30</sup>) - 2 | | 5 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 10 | e | → 9 |
|
| 10 | e | → 9 |
|
||||||
| 9 | d | → (2<sup>30</sup>) - 1 |
|
| 9 | d | → (2<sup>30</sup>) - 2 |
|
||||||
| 8 | c | 5 |
|
| 8 | c | 5 |
|
||||||
| 7 | b | → 4 |
|
| 7 | b | → 4 |
|
||||||
| 6 | a | → 0 |
|
| 6 | a | → 0 |
|
||||||
|
@ -439,24 +439,24 @@ Next, `foo()` calls `bar()` with `x` and `z`:
|
||||||
| 4 | y | 10 |
|
| 4 | y | 10 |
|
||||||
| 3 | x | → 0 |
|
| 3 | x | → 0 |
|
||||||
| 2 | j | → 0 |
|
| 2 | j | → 0 |
|
||||||
| 1 | i | → 2<sup>30</sup> |
|
| 1 | i | → (2<sup>30</sup>) - 1 |
|
||||||
| 0 | h | 3 |
|
| 0 | h | 3 |
|
||||||
|
|
||||||
We end up allocating another value on the heap, and so we have to subtract one
|
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
|
from (2<sup>30</sup>) - 1. It’s easier to just write that than `1,073,741,822`. In any
|
||||||
case, we set up the variables as usual.
|
case, we set up the variables as usual.
|
||||||
|
|
||||||
At the end of `bar()`, it calls `baz()`:
|
At the end of `bar()`, it calls `baz()`:
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|----------------------|------|------------------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 20 |
|
| (2<sup>30</sup>) - 1 | | 20 |
|
||||||
| (2<sup>30</sup>) - 1 | | 5 |
|
| (2<sup>30</sup>) - 2 | | 5 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 12 | g | 100 |
|
| 12 | g | 100 |
|
||||||
| 11 | f | → 9 |
|
| 11 | f | → 9 |
|
||||||
| 10 | e | → 9 |
|
| 10 | e | → 9 |
|
||||||
| 9 | d | → (2<sup>30</sup>) - 1 |
|
| 9 | d | → (2<sup>30</sup>) - 2 |
|
||||||
| 8 | c | 5 |
|
| 8 | c | 5 |
|
||||||
| 7 | b | → 4 |
|
| 7 | b | → 4 |
|
||||||
| 6 | a | → 0 |
|
| 6 | a | → 0 |
|
||||||
|
@ -464,7 +464,7 @@ At the end of `bar()`, it calls `baz()`:
|
||||||
| 4 | y | 10 |
|
| 4 | y | 10 |
|
||||||
| 3 | x | → 0 |
|
| 3 | x | → 0 |
|
||||||
| 2 | j | → 0 |
|
| 2 | j | → 0 |
|
||||||
| 1 | i | → 2<sup>30</sup> |
|
| 1 | i | → (2<sup>30</sup>) - 1 |
|
||||||
| 0 | h | 3 |
|
| 0 | h | 3 |
|
||||||
|
|
||||||
With this, we’re at our deepest point! Whew! Congrats for following along this
|
With this, we’re at our deepest point! Whew! Congrats for following along this
|
||||||
|
@ -474,11 +474,11 @@ After `baz()` is over, we get rid of `f` and `g`:
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|----------------------|------|------------------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 20 |
|
| (2<sup>30</sup>) - 1 | | 20 |
|
||||||
| (2<sup>30</sup>) - 1 | | 5 |
|
| (2<sup>30</sup>) - 2 | | 5 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 10 | e | → 9 |
|
| 10 | e | → 9 |
|
||||||
| 9 | d | → (2<sup>30</sup>) - 1 |
|
| 9 | d | → (2<sup>30</sup>) - 2 |
|
||||||
| 8 | c | 5 |
|
| 8 | c | 5 |
|
||||||
| 7 | b | → 4 |
|
| 7 | b | → 4 |
|
||||||
| 6 | a | → 0 |
|
| 6 | a | → 0 |
|
||||||
|
@ -486,32 +486,32 @@ After `baz()` is over, we get rid of `f` and `g`:
|
||||||
| 4 | y | 10 |
|
| 4 | y | 10 |
|
||||||
| 3 | x | → 0 |
|
| 3 | x | → 0 |
|
||||||
| 2 | j | → 0 |
|
| 2 | j | → 0 |
|
||||||
| 1 | i | → 2<sup>30</sup> |
|
| 1 | i | → (2<sup>30</sup>) - 1 |
|
||||||
| 0 | h | 3 |
|
| 0 | h | 3 |
|
||||||
|
|
||||||
Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees
|
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.
|
what it points to: (2<sup>30</sup>) - 2.
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|-----------------|------|------------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 20 |
|
| (2<sup>30</sup>) - 1 | | 20 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 5 | z | → 4 |
|
| 5 | z | → 4 |
|
||||||
| 4 | y | 10 |
|
| 4 | y | 10 |
|
||||||
| 3 | x | → 0 |
|
| 3 | x | → 0 |
|
||||||
| 2 | j | → 0 |
|
| 2 | j | → 0 |
|
||||||
| 1 | i | → 2<sup>30</sup> |
|
| 1 | i | → (2<sup>30</sup>) - 1 |
|
||||||
| 0 | h | 3 |
|
| 0 | h | 3 |
|
||||||
|
|
||||||
And after that, `foo()` returns:
|
And after that, `foo()` returns:
|
||||||
|
|
||||||
| Address | Name | Value |
|
| Address | Name | Value |
|
||||||
|-----------------|------|------------------|
|
|----------------------|------|------------------------|
|
||||||
| 2<sup>30</sup> | | 20 |
|
| (2<sup>30</sup>) - 1 | | 20 |
|
||||||
| ... | ... | ... |
|
| ... | ... | ... |
|
||||||
| 2 | j | → 0 |
|
| 2 | j | → 0 |
|
||||||
| 1 | i | → 2<sup>30</sup> |
|
| 1 | i | → (2<sup>30</sup>) - 1 |
|
||||||
| 0 | h | 3 |
|
| 0 | h | 3 |
|
||||||
|
|
||||||
And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
|
And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
|
||||||
it will clean up the last of the heap too.
|
it will clean up the last of the heap too.
|
||||||
|
|
Loading…
Reference in a new issue