liveBook · Manning

Undefined behavior

As explained in Learn Rust in a Month of Lunches

Undefined behavior is program execution whose effects are not constrained by the language specification because a required safety invariant has been violated.

Undefined behavior, often shortened to UB, occurs when unsafe code violates a safety rule and the language no longer promises what execution will do. Rust uses unsafe blocks to permit operations whose safety must be guaranteed by the programmer. section 16.4.2 section 16.4.4

Two examples show why UB can look harmless at first:

  • A mutable static can produce a data race when several threads update it simultaneously. Small tests may print the expected value, while larger runs lose increments and produce varying results. section 16.4.2
  • An _unchecked method skips a check. Calling Option::unwrap_unchecked() on Some(10) works, but calling it on None can terminate the program with a core dump. section 16.4.4
  • Safe alternatives such as Arc<Mutex> preserve controlled access, while ordinary checked methods avoid relying on an assumption the compiler cannot verify. section 16.4.2 section 16.4.4

A race hidden by a successful test

Ten threads incrementing a mutable static ten times may print 100. Increasing the workload to 1,000 threads and 1,000 increments can instead print values such as 959,696 or 825,266, because simultaneous reads and writes overwrite one another. section 16.4.2

error[E0133]: use of mutable static is unsafe and requires unsafe function
or block
 --> src/main.rs:4:5
  |
4 |     NUMBER += 1;
  |     ^^^^^^^^^^^ use of mutable static
  |
  = note: mutable statics can be mutated by multiple threads: aliasing
violations or data races will cause undefined behavior

Compiler feedback identifies mutable static access as unsafe and names aliasing violations and data races as possible causes of undefined behavior. section 16.4.2

How Learn Rust in a Month of Lunches covers it

How deep it goes
Demonstrates UB through races and invalid unchecked unwrapping, but does not develop a formal language-level taxonomy.
Examples
Uses concurrent increments of static mut and invalid Option::unwrap_unchecked() calls.
What it assumes
Assumes basic Rust syntax and threads while explaining unsafe blocks, mutable statics, and unchecked methods in plain examples.
What you can do after
Diagnose unsafe operations by reading compiler warnings and recognizing races or violated unchecked assumptions.
How it connects
Connects undefined behavior with unsafe Rust, mutable statics, data races, aliasing, and mutexes.

Also explained in

Compare how 7 books explain undefined behavior →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.