-
Notifications
You must be signed in to change notification settings - Fork 13.3k
TRPL: the stack and the heap #25292
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
Conversation
(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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
familiar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ugh thanks!
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. |
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
\o/ |
| 2 | b | 100 | | ||
| 1 | a | 5 | | ||
| 0 | x | 42 | | ||
|
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice catch
👍 (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. |
There was a problem hiding this comment.
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
, and2
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:
- First change the original example to use explicit
i32
andi64
type annotations, and then - use a somewhat more realistic sequence of addresses here, like
1000, 1004, 1008, ...
, - (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.)
There was a problem hiding this comment.
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.
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? |
@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. |
@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 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
bb66c1f
to
e66653b
Compare
so, lgtm. the other comments have given really thorough reviews that cover everything I would say. r+ |
@bors: r=nikomatsakis rollup |
📌 Commit e66653b has been approved by |
…matsakis I think someday I'd like to make these drawings rather than text, but for now, this will have to be good enough.
…matsakis I think someday I'd like to make these drawings rather than text, but for now, this will have to be good enough.
I think someday I'd like to make these drawings rather than text, but for now, this will have to be good enough.