2022-12-21 16:36:30 +01:00
# Stack Memory
Creating a `String` puts fixed-sized data on the stack and dynamically sized
data on the heap:
```rust,editable
fn main() {
let s1 = String::from("Hello");
}
```
```bob
Stack Heap
.- - - - - - - - - - - - - -. .- - - - - - - - - - - - - - - -.
: : : :
: s1 : : :
: +-----------+-------+ : : +----+----+----+----+----+ :
: | ptr | o---+---+-----+-->| H | e | l | l | o | :
: | len | 5 | : : +----+----+----+----+----+ :
: | capacity | 5 | : : :
: +-----------+-------+ : : :
: : `- - - - - - - - - - - - - - - -'
`- - - - - - - - - - - - - -'
```
2023-01-12 11:12:53 +09:00
<details>
* Mention that a `String` is backed by a `Vec` , so it has a capacity and length and can grow if mutable via reallocation on the heap.
2023-01-12 11:51:37 +01:00
* 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]
2023-01-12 11:12:53 +09:00
2023-02-09 06:47:15 +00:00
* We can inspect the memory layout with `unsafe` code. However, you should point out that this is rightfully unsafe!
2023-03-11 14:12:32 -08:00
```rust,editable
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}");
}
2023-02-09 06:47:15 +00:00
}
2023-03-11 14:12:32 -08:00
```
2023-02-09 06:47:15 +00:00
2023-01-12 11:12:53 +09:00
</details>
[System Allocator]: https://doc.rust-lang.org/std/alloc/struct.System.html
2023-01-12 11:51:37 +01:00
[Allocator API]: https://doc.rust-lang.org/std/alloc/index.html