Primitive type - stack,
Array(data) - stack?
Slice(data) - stack?
Struct - heap?
Vector(data) - heap?
Primitive type - stack,
Rust actually makes it very clear where different data types are allocated. By default, all bare types are allocated on the stack.
struct goes on the stack unless placed in a
Vec, etc. Same with arrays.
Slices can refer to heap or stack allocated data; they only contain a pointer to somewhere else and a count of available values. In fact, it is safe to transmute
&[T; 1] or
&[T] with a length of 1, because the layout of the data it points to is the same.
Is there a way to figure out what else might fall under the “etc” category? (Other than reading the source)
The source. Or the documentation.
Things which are
Copy generally don’t own heap values; things which are
But the distinction between stack and heap doesn’t matter so much in Rust.
Copy and ownership are more important, and thinking in terms of these is easier.
Generally, anything where the size of the data it contains cannot be determined at compile time, or when a consistent location in memory is required and a static too accessible or long-lived.
- Vec, VecDeque
- HashMap, HashSet
- BTreeMap, BTreeSet
thread::spawn(): the closure is boxed so it can be passed as a pointer into the new thread’s environment (required by the C-based thread APIs)
JoinHandle: the return value of the closure passed to
thread::spawn()is returned as a pointer (same)
- Sender/SyncSender & Receiver
- The TCP streams are buffered at the OS level, I don’t know how much Rust has a say in those buffer sizes
- stdin, stdout, and stderr use global heap-allocated buffers (which you interact with whenever you invoke
I’m probably missing a lot but those are some of the more common examples of heap allocation done in the stdlib.
Another way of thinking about this is that Rust will stack allocate everything, unless you specifically use
alloc::heap::allocate() or the
box keyword. Types may use this internally. For example, when you create a new
Arc<T>, it uses
box internally: https://github.com/rust-lang/rust/blob/master/src/liballoc/arc.rs#L188
That’s why it’s on the heap. It’s not that Rust itself chooses to default to allocate, it’s that you create an
Arc<T> struct on the stack, and its
new() function creates a space on the heap, and then sets a pointer to that heap-allocated memory from inside your stack-allocated
struct. We conversationally say that
Arc<T> is “on the heap”, but it’s really the contents that are.
Does that help?
Speaking of the box keyword, any news on when that goes into stable?