Skip to content

Commit cbf4c34

Browse files
committed
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
2 parents 920cf4b + bcf3921 commit cbf4c34

File tree

1 file changed

+133
-133
lines changed

1 file changed

+133
-133
lines changed

src/doc/trpl/the-stack-and-the-heap.md

+133-133
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,12 @@ on the heap. The actual value of the box is a structure which has a pointer to
217217
it allocates some memory for the heap, and puts `5` there. The memory now looks
218218
like this:
219219

220-
| Address | Name | Value |
221-
|-----------------|------|----------------|
222-
| 2<sup>30</sup> | | 5 |
223-
| ... | ... | ... |
224-
| 1 | y | 42 |
225-
| 0 | x | 2<sup>30</sup> |
220+
| Address | Name | Value |
221+
|-----------------|------|------------------|
222+
| 2<sup>30</sup> | | 5 |
223+
| ... | ... | ... |
224+
| 1 | y | 42 |
225+
| 0 | x | 2<sup>30</sup> |
226226

227227
We have 2<sup>30</sup> in our hypothetical computer with 1GB of RAM. And since
228228
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
242242
layout of a program which has been running for a while now:
243243

244244

245-
| Address | Name | Value |
246-
|----------------------|------|----------------------|
247-
| 2<sup>30</sup> | | 5 |
248-
| (2<sup>30</sup>) - 1 | | |
249-
| (2<sup>30</sup>) - 2 | | |
250-
| (2<sup>30</sup>) - 3 | | 42 |
251-
| ... | ... | ... |
252-
| 3 | y | (2<sup>30</sup>) - 3 |
253-
| 2 | y | 42 |
254-
| 1 | y | 42 |
255-
| 0 | x | 2<sup>30</sup> |
245+
| Address | Name | Value |
246+
|----------------------|------|------------------------|
247+
| 2<sup>30</sup> | | 5 |
248+
| (2<sup>30</sup>) - 1 | | |
249+
| (2<sup>30</sup>) - 2 | | |
250+
| (2<sup>30</sup>) - 3 | | 42 |
251+
| ... | ... | ... |
252+
| 3 | y | (2<sup>30</sup>) - 3 |
253+
| 2 | y | 42 |
254+
| 1 | y | 42 |
255+
| 0 | x | 2<sup>30</sup> |
256256

257257
In this case, we’ve allocated four things on the heap, but deallocated two of
258258
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() {
304304

305305
When we enter `main()`, memory looks like this:
306306

307-
| Address | Name | Value |
308-
|---------|------|-------|
309-
| 1 | y | 0 |
310-
| 0 | x | 5 |
307+
| Address | Name | Value |
308+
|---------|------|--------|
309+
| 1 | y | → 0 |
310+
| 0 | x | 5 |
311311

312312
`x` is a plain old `5`, and `y` is a reference to `x`. So its value is the
313313
memory location that `x` lives at, which in this case is `0`.
314314

315315
What about when we call `foo()`, passing `y` as an argument?
316316

317-
| Address | Name | Value |
318-
|---------|------|-------|
319-
| 3 | z | 42 |
320-
| 2 | i | 0 |
321-
| 1 | y | 0 |
322-
| 0 | x | 5 |
317+
| Address | Name | Value |
318+
|---------|------|--------|
319+
| 3 | z | 42 |
320+
| 2 | i | → 0 |
321+
| 1 | y | → 0 |
322+
| 0 | x | 5 |
323323

324324
Stack frames aren’t just for local bindings, they’re for arguments too. So in
325325
this case, we need to have both `i`, our argument, and `z`, our local variable
@@ -366,152 +366,152 @@ fn main() {
366366

367367
First, we call `main()`:
368368

369-
| Address | Name | Value |
370-
|-----------------|------|----------------|
371-
| 2<sup>30</sup> | | 20 |
372-
| ... | ... | ... |
373-
| 2 | j | 0 |
374-
| 1 | i | 2<sup>30</sup> |
375-
| 0 | h | 3 |
369+
| Address | Name | Value |
370+
|-----------------|------|------------------|
371+
| 2<sup>30</sup> | | 20 |
372+
| ... | ... | ... |
373+
| 2 | j | 0 |
374+
| 1 | i | 2<sup>30</sup> |
375+
| 0 | h | 3 |
376376

377377
We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
378378
value pointing there.
379379

380380
Next, at the end of `main()`, `foo()` gets called:
381381

382-
| Address | Name | Value |
383-
|-----------------|------|----------------|
384-
| 2<sup>30</sup> | | 20 |
385-
| ... | ... | ... |
386-
| 5 | z | 4 |
387-
| 4 | y | 10 |
388-
| 3 | x | 0 |
389-
| 2 | j | 0 |
390-
| 1 | i | 2<sup>30</sup> |
391-
| 0 | h | 3 |
382+
| Address | Name | Value |
383+
|-----------------|------|-----------------|
384+
| 2<sup>30</sup> | | 20 |
385+
| ... | ... | ... |
386+
| 5 | z | → 4 |
387+
| 4 | y | 10 |
388+
| 3 | x | → 0 |
389+
| 2 | j | → 0 |
390+
| 1 | i | 2<sup>30</sup>|
391+
| 0 | h | 3 |
392392

393393
Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value
394394
as `j`, since that’s what we passed it in. It’s a pointer to the `0` address,
395395
since `j` points at `h`.
396396

397397
Next, `foo()` calls `baz()`, passing `z`:
398398

399-
| Address | Name | Value |
400-
|-----------------|------|----------------|
401-
| 2<sup>30</sup> | | 20 |
402-
| ... | ... | ... |
403-
| 7 | g | 100 |
404-
| 6 | f | 4 |
405-
| 5 | z | 4 |
406-
| 4 | y | 10 |
407-
| 3 | x | 0 |
408-
| 2 | j | 0 |
409-
| 1 | i | 2<sup>30</sup> |
410-
| 0 | h | 3 |
399+
| Address | Name | Value |
400+
|-----------------|------|------------------|
401+
| 2<sup>30</sup> | | 20 |
402+
| ... | ... | ... |
403+
| 7 | g | 100 |
404+
| 6 | f | 4 |
405+
| 5 | z | 4 |
406+
| 4 | y | 10 |
407+
| 3 | x | 0 |
408+
| 2 | j | 0 |
409+
| 1 | i | 2<sup>30</sup> |
410+
| 0 | h | 3 |
411411

412412
We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s
413413
over, we get rid of its stack frame:
414414

415-
| Address | Name | Value |
416-
|-----------------|------|----------------|
417-
| 2<sup>30</sup> | | 20 |
418-
| ... | ... | ... |
419-
| 5 | z | 4 |
420-
| 4 | y | 10 |
421-
| 3 | x | 0 |
422-
| 2 | j | 0 |
423-
| 1 | i | 2<sup>30</sup> |
424-
| 0 | h | 3 |
415+
| Address | Name | Value |
416+
|-----------------|------|------------------|
417+
| 2<sup>30</sup> | | 20 |
418+
| ... | ... | ... |
419+
| 5 | z | 4 |
420+
| 4 | y | 10 |
421+
| 3 | x | 0 |
422+
| 2 | j | 0 |
423+
| 1 | i | 2<sup>30</sup> |
424+
| 0 | h | 3 |
425425

426426
Next, `foo()` calls `bar()` with `x` and `z`:
427427

428-
| Address | Name | Value |
429-
|----------------------|------|----------------------|
430-
| 2<sup>30</sup> | | 20 |
431-
| (2<sup>30</sup>) - 1 | | 5 |
432-
| ... | ... | ... |
433-
| 10 | e | 9 |
434-
| 9 | d | (2<sup>30</sup>) - 1 |
435-
| 8 | c | 5 |
436-
| 7 | b | 4 |
437-
| 6 | a | 0 |
438-
| 5 | z | 4 |
439-
| 4 | y | 10 |
440-
| 3 | x | 0 |
441-
| 2 | j | 0 |
442-
| 1 | i | 2<sup>30</sup> |
443-
| 0 | h | 3 |
428+
| Address | Name | Value |
429+
|----------------------|------|------------------------|
430+
| 2<sup>30</sup> | | 20 |
431+
| (2<sup>30</sup>) - 1 | | 5 |
432+
| ... | ... | ... |
433+
| 10 | e | 9 |
434+
| 9 | d | (2<sup>30</sup>) - 1 |
435+
| 8 | c | 5 |
436+
| 7 | b | 4 |
437+
| 6 | a | 0 |
438+
| 5 | z | 4 |
439+
| 4 | y | 10 |
440+
| 3 | x | 0 |
441+
| 2 | j | 0 |
442+
| 1 | i | 2<sup>30</sup> |
443+
| 0 | h | 3 |
444444

445445
We end up allocating another value on the heap, and so we have to subtract one
446446
from 2<sup>30</sup>. It’s easier to just write that than `1,073,741,823`. In any
447447
case, we set up the variables as usual.
448448

449449
At the end of `bar()`, it calls `baz()`:
450450

451-
| Address | Name | Value |
452-
|----------------------|------|----------------------|
453-
| 2<sup>30</sup> | | 20 |
454-
| (2<sup>30</sup>) - 1 | | 5 |
455-
| ... | ... | ... |
456-
| 12 | g | 100 |
457-
| 11 | f | 9 |
458-
| 10 | e | 9 |
459-
| 9 | d | (2<sup>30</sup>) - 1 |
460-
| 8 | c | 5 |
461-
| 7 | b | 4 |
462-
| 6 | a | 0 |
463-
| 5 | z | 4 |
464-
| 4 | y | 10 |
465-
| 3 | x | 0 |
466-
| 2 | j | 0 |
467-
| 1 | i | 2<sup>30</sup> |
468-
| 0 | h | 3 |
451+
| Address | Name | Value |
452+
|----------------------|------|------------------------|
453+
| 2<sup>30</sup> | | 20 |
454+
| (2<sup>30</sup>) - 1 | | 5 |
455+
| ... | ... | ... |
456+
| 12 | g | 100 |
457+
| 11 | f | 9 |
458+
| 10 | e | 9 |
459+
| 9 | d | (2<sup>30</sup>) - 1 |
460+
| 8 | c | 5 |
461+
| 7 | b | 4 |
462+
| 6 | a | 0 |
463+
| 5 | z | 4 |
464+
| 4 | y | 10 |
465+
| 3 | x | 0 |
466+
| 2 | j | 0 |
467+
| 1 | i | 2<sup>30</sup> |
468+
| 0 | h | 3 |
469469

470470
With this, we’re at our deepest point! Whew! Congrats for following along this
471471
far.
472472

473473
After `baz()` is over, we get rid of `f` and `g`:
474474

475-
| Address | Name | Value |
476-
|----------------------|------|----------------------|
477-
| 2<sup>30</sup> | | 20 |
478-
| (2<sup>30</sup>) - 1 | | 5 |
479-
| ... | ... | ... |
480-
| 10 | e | 9 |
481-
| 9 | d | (2<sup>30</sup>) - 1 |
482-
| 8 | c | 5 |
483-
| 7 | b | 4 |
484-
| 6 | a | 0 |
485-
| 5 | z | 4 |
486-
| 4 | y | 10 |
487-
| 3 | x | 0 |
488-
| 2 | j | 0 |
489-
| 1 | i | 2<sup>30</sup> |
490-
| 0 | h | 3 |
475+
| Address | Name | Value |
476+
|----------------------|------|------------------------|
477+
| 2<sup>30</sup> | | 20 |
478+
| (2<sup>30</sup>) - 1 | | 5 |
479+
| ... | ... | ... |
480+
| 10 | e | 9 |
481+
| 9 | d | (2<sup>30</sup>) - 1 |
482+
| 8 | c | 5 |
483+
| 7 | b | 4 |
484+
| 6 | a | 0 |
485+
| 5 | z | 4 |
486+
| 4 | y | 10 |
487+
| 3 | x | 0 |
488+
| 2 | j | 0 |
489+
| 1 | i | 2<sup>30</sup> |
490+
| 0 | h | 3 |
491491

492492
Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees
493493
what it points to: (2<sup>30</sup>) - 1.
494494

495-
| Address | Name | Value |
496-
|-----------------|------|----------------|
497-
| 2<sup>30</sup> | | 20 |
498-
| ... | ... | ... |
499-
| 5 | z | 4 |
500-
| 4 | y | 10 |
501-
| 3 | x | 0 |
502-
| 2 | j | 0 |
503-
| 1 | i | 2<sup>30</sup> |
504-
| 0 | h | 3 |
495+
| Address | Name | Value |
496+
|-----------------|------|------------------|
497+
| 2<sup>30</sup> | | 20 |
498+
| ... | ... | ... |
499+
| 5 | z | 4 |
500+
| 4 | y | 10 |
501+
| 3 | x | 0 |
502+
| 2 | j | 0 |
503+
| 1 | i | 2<sup>30</sup> |
504+
| 0 | h | 3 |
505505

506506
And after that, `foo()` returns:
507507

508-
| Address | Name | Value |
509-
|-----------------|------|----------------|
510-
| 2<sup>30</sup> | | 20 |
511-
| ... | ... | ... |
512-
| 2 | j | 0 |
513-
| 1 | i | 2<sup>30</sup> |
514-
| 0 | h | 3 |
508+
| Address | Name | Value |
509+
|-----------------|------|------------------|
510+
| 2<sup>30</sup> | | 20 |
511+
| ... | ... | ... |
512+
| 2 | j | 0 |
513+
| 1 | i | 2<sup>30</sup> |
514+
| 0 | h | 3 |
515515

516516
And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
517517
it will clean up the last of the heap too.

0 commit comments

Comments
 (0)