You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-12-23 15:01:49 +02:00
* Indent code in speaker notes #475 * Update stack.md * Update destructuring-arrays.md * Update hashmap.md * Update traits.md
1.9 KiB
1.9 KiB
Stack Memory
Creating a String puts fixed-sized data on the stack and dynamically sized
data on the heap:
fn main() {
let s1 = String::from("Hello");
}
Stack Heap
.- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.
: : : :
: s1 : : :
: +-----------+-------+ : : +----+----+----+----+----+ :
: | ptr | o---+---+-----+-->| H | e | l | l | o | :
: | len | 5 | : : +----+----+----+----+----+ :
: | capacity | 5 | : : :
: +-----------+-------+ : : :
: : `- - - - - - - - - - - - - - - -'
`- - - - - - - - - - - - - -'
-
Mention that a
Stringis backed by aVec, so it has a capacity and length and can grow if mutable via reallocation on the heap. -
If students ask about it, you can mention that the underlying memory is heap allocated using the System Allocator and custom allocators can be implemented using the Allocator API
-
We can inspect the memory layout with
unsafecode. However, you should point out that this is rightfully unsafe!fn main() { let mut s1 = String::from("Hello"); s1.push(' '); s1.push_str("world"); // DON'T DO THIS AT HOME! For educational purposes only. // String provides no guarantees about its layout, so this could lead to // undefined behavior. unsafe { let (capacity, ptr, len): (usize, usize, usize) = std::mem::transmute(s1); println!("ptr = {ptr:#x}, len = {len}, capacity = {capacity}"); } }