Review of Program Memory

Programs allocate memory in two ways:

  • Stack: Kontinuierlicher Speicherbereich fĂŒr lokale Variablen.

    • Werte haben feste GrĂ¶ĂŸen, die zur Kompilierzeit bekannt sind.
    • Extrem schnell: Durch Bewegen eines Stapelzeigers.
    • Einfach zu verwalten: folgt Funktionsaufrufen.
    • Große SpeicherlokalitĂ€t (memory locality).
  • Heap: Speicherung von Werten außerhalb von Funktionsaufrufen.

    • Werte haben dynamische GrĂ¶ĂŸen, die zur Laufzeit bestimmt werden.
    • Etwas langsamer als der Stapel: Etwas Buchhaltung ist erforderlich.
    • Keine Garantie fĂŒr SpeicherlokalitĂ€t.

Beispiel

Creating a String puts fixed-sized metadata on the stack and dynamically sized data, the actual string, on the heap:

fn main() {
    let s1 = String::from("Hello");
}
StackHeaps1ptrHellolen5capacity5
This slide should take about 5 minutes.
  • 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.

  • 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

More to Explore

We can inspect the memory layout with unsafe Rust. 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 (ptr, capacity, len): (usize, usize, usize) = std::mem::transmute(s1);
        println!("ptr = {ptr:#x}, len = {len}, capacity = {capacity}");
    }
}