Skip to content

Week 2 - Memory Layout: Stack, Heap, Data, BSS, TLS

2.1 Conceptual Core

  • A Rust value lives in exactly one of: a stack frame, the heap (via an allocator), .data (mutable static), .rodata (immutable static / const), .bss (zero-initialized static), or thread-local storage.
  • let x = 5; puts x on the stack. Box::new(5) puts the integer on the heap and a pointer on the stack. static X: i32 = 5; puts X in .rodata. static mut Y: i32 = 0; puts Y in .data. Internalize this taxonomy before writing another line of code.
  • const vs static: const is inlined at every use site (no address); static has a stable address. The distinction matters for FFI and for sharing across threads.

2.2 Mechanical Detail

  • std::mem::size_of, align_of, size_of_val, align_of_val. Run them on (), bool, &u8, &[u8], &dyn Debug, Box<dyn Debug>, Option<&T>, Option<Box<T>>. Predict the answers, then check.
  • Niche optimization: Option<&T> is 8 bytes, not 16, because the null pointer is the niche. Option<Box<T>> likewise. Learn to spot when you've broken the niche by adding a redundant variant.
  • #[repr(C)], #[repr(transparent)], #[repr(packed)], #[repr(align(N))]: when each is appropriate. Default #[repr(Rust)] reorders fields for tightest packing-this is observable via - -print=type-sizes` (nightly).
  • Thread-local storage: thread_local! macro, the OS-level cost (__tls_get_addr on Linux glibc), and why it is rarely the right answer.

2.3 Lab-"Layout Forensics"

Build a binary that allocates one value of each "kind": - a stack [u8; 64], - a Box<[u8; 64]>, - a static FOO: [u8; 64] = [0xAB; 64];, - a static mut BAR: [u8; 64] = [0; 64];, - a thread_local! RefCell<[u8; 64]>.

Print the address of each (&value as *const _ as usize). Run under cat /proc/self/maps (spawn cat from inside the program) and prove which segment each address falls in. Write up the mapping in NOTES.md.

2.4 Idiomatic & Clippy Drill

  • Lints to study: clippy::large_stack_arrays, clippy::large_enum_variant, clippy::box_collection, clippy::vec_box. Each maps to a layout pathology.

2.5 Production Hardening Slice

  • Set RUSTFLAGS="-C link-arg=-Wl,--print-memory-usage" (or use cargo-bloat) to inspect per-section binary footprint. Add cargo bloat --release --crates output to NOTES.md. This is the baseline for size-budget conversations later.

Comments