Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TRPL: the stack and the heap #25292

Merged
merged 1 commit into from May 12, 2015
Merged

Conversation

steveklabnik
Copy link
Member

I think someday I'd like to make these drawings rather than text, but for now, this will have to be good enough.

@rust-highfive
Copy link
Collaborator

r? @nikomatsakis

(rust_highfive has picked a reviewer for you, use r? to override)

Coming Soon
As a systems language, Rust operates at a low level. If you’re coming from a
high-level language, there’s some aspects of systems programming that you may
not be familliar with. The most important one is how memory works, with a stack

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

familiar

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh thanks!

@asolove
Copy link

asolove commented May 11, 2015

As someone coming to Rust from dynamic, GC'd languages, I found this really helpful and wish I had read it a few weeks ago.

One comment: the beginning says people who understand the stack and the heap can skip this, and I almost stopped reading there. I already knew in the abstract what the stack and the heap are. But the real thing I learned from reading this was the implications of local variables being names for stack locations. It brought back to mind this excellent description of the difference between Python and C variables.

@robmiller
Copy link

As a high level programmer and therefore in the target audience, I found this very clear and easy to follow. The only thing that I thought at the end was: I'm still not 100% sure when I'd use the heap in a practical situation, but that could just be a failure of my imagination!

[rawpointer]: raw-pointers.html

Since this memory is on the heap, it can stay alive longer than the function
which allocates the box. In this case, however, it doesn’t. When the function
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps mention somewhere that it is possible to make this happen by moving out of the function (or "changing owners" or whatever). To me this seemed to read that in Rust you can't move boxes out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, for sure. I'll add something about this.

@Manishearth
Copy link
Member

\o/

| 2 | b | 100 |
| 1 | a | 5 |
| 0 | x | 42 |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've deallocated one variable too many here. c is a variable in foo too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch

@killercup
Copy link
Member

👍

(I'd like to see that dishes metaphor extended to likening the heap to a dishwasher, though! ;))

| 0 | x | 42 |

Because `0` was taken by the first frame, `1` and `2` are used for `foo()`’s
stack frame. It grows upward, the more functions we call.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading this, there is a potentially interesting ambiguity, especially for a reader who is a true novice to Rust, but not to low-level programming.

Namely: are these addresses really separated by one unit each (0, 1, 2, ...)?

  • One obvious response is "probably not, since we are (probably) on a byte-addressed machine, which means that each address can potentially refer to an individual byte of memory, and thus each increment here represents a shift of a single byte, but our values are more than one byte apart, right?"
    • But, ah ha, the Rust novice, forgetting how integer-fallback works, might think "oh, in the example as we have seen it so far, all of the numbers have been less than or equal to 100. Each of those can fit into a byte, so maybe the addresses really do go up by one byte at a time."
    • (Is it strange to imagine a person reaching such a conclusion? I'm all about anticipating the worst case for human mental models...)

Anyway, I suggest that you add a parenthetical note here that:

  • The numbers 0, 1, and 2 are all solely for illustrative purposes, and bear no relationship to the actual numbers the computer will actually use.
  • In particular, the series of addresses are in reality going to be separated by some number of bytes that separate each address, and that separation may even exceed the size of the value being stored.

Alternative

Or perhaps better still, bite the bullet:

  1. First change the original example to use explicit i32 and i64 type annotations, and then
  2. use a somewhat more realistic sequence of addresses here, like 1000, 1004, 1008, ...,
  3. (and then be sure to use an appropriate value when discussing pointer-sized types like Box below).

So I guess I would make the example look like:

fn foo() {
    let y: i64 = 5;
    let z: i32 = 100;
}

fn main() {
    let x: i32 = 42;

    foo();
}

and make the table then look like:

| Address | Name | #Bytes | Value |
+---------+------+--------+-------+
| 1012    | z    | 4      | 100   |
| 1004    | y    | 8      | 5     |
| 1000    | x    | 4      | 42    |

(even here I would still probably note that the addresses listed probably do not match what one will see in practice, since there is likely to be e.g. padding words between the two stack frames to ensure that each frame meets some expected alignment, depending on the target ABI, e.g. 16-byte alignment.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for now, I'm going to add the paragraph. I can see this expanding with the later example, but for now, I want to ship the basics.

@steveklabnik
Copy link
Member Author

All review concerns addressed, I think, except for the stack growing in the wrong direction. It's true that on most systems, this goes the other direction, and the addresses are much harder to understand if they go in the other direction. So what do we think? Should we make it go the other way, at the cost of some complexity, but being more accurate on the majority of architectures?

@robmiller
Copy link

@steveklabnik it's not simpler understand one versus the other, so it's not like it's a convenient abstraction to make it easier to explain. For that reason, I don't see why you wouldn't have it in the examples the way it is in reality.

@steveklabnik
Copy link
Member Author

@robmiller the way I'm doing it, the addresses are mostly 1, 2, 3, 4, 5.

Flipping it around would make it (2^30)-1, (2^30)-2, (2^30)-3, etc. Smaller numbers are easier for people to reason about.

high-level language, there are some aspects of systems programming that you may
not be familiar with. The most important one is how memory works, with a stack
and a heap. If you’re familiar with the terms ‘stack’ and ‘heap’ with regards
to memory management, this chapter will be a refresher. If you’re not, you’ll
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps change to "if you're familiar with how C-like languages use stack allocation, ...", per the feedback

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that sounds even better. will do now

@nikomatsakis
Copy link
Contributor

so, lgtm. the other comments have given really thorough reviews that cover everything I would say. r+

@steveklabnik
Copy link
Member Author

@bors: r=nikomatsakis rollup

@bors
Copy link
Contributor

bors commented May 11, 2015

📌 Commit e66653b has been approved by nikomatsakis

steveklabnik added a commit to steveklabnik/rust that referenced this pull request May 11, 2015
…matsakis

I think someday I'd like to make these drawings rather than text, but for now, this will have to be good enough.
bors added a commit that referenced this pull request May 11, 2015
steveklabnik added a commit to steveklabnik/rust that referenced this pull request May 12, 2015
…matsakis

I think someday I'd like to make these drawings rather than text, but for now, this will have to be good enough.
bors added a commit that referenced this pull request May 12, 2015
@bors bors merged commit e66653b into rust-lang:master May 12, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet