Undefined Behavior

Undefined behavior, often abbreviated UB, is the result of a violated assumption of the compiler or optimizer. UB can usually only be encountered if the program or its dependencies use unsafe code incorrectly.

There are a few known bugs that can cause UB without  in edge cases, which are labeled I-unsound on GitHub. However, it's very unlikely to encounter these bugs on a day-to-day basis.

Example
This example uses the unsafe function to convert the integer   to a. The problem is that Rust assumes that any  is either   (represented as  ) or   (represented as  ). This means that  is in an invalid state – it is neither   nor.

This means that the compiler is free to assume that the code will never run and therefore can make certain optimizations, which can have drastic consequences in other parts of the code. This series of articles explains the impacts of UB; it focuses on C but the points also apply to Rust.

What happens when Undefined Behavior is encountered
The compiler assumes that UB can never happen, and optimizes code under this assumption. However, optimizations that are correct in the absence of UB might be nonsensical and even dangerous, if UB is present. What exactly happens is not specified and can't be predicted. For example, the optimizer is allowed to inline code and move code around, to unroll loops, replace arithmetic with bitwise operations, remove "dead code" and much more. So it is possible that code exhibiting UB could be removed alltogether, or do something entirely else. This is sometimes called "eating your laundry".

Sources of Undefined Behavior
This is an incomplete lists of things that can cause undefined behavior:

Invalid state
Many types only allow certain values. For example,  can only be   or. References must not be NULL. Enums can only have specific values as well. When transmuting types, values in an invalid state can be created.

Reading uninitialized memory
This can happen when using the deprecated function or  incorrectly.

Use after free
This occurs when you attempt to use a value whose destructor has already been run. This can happen when a transmuted value has the wrong lifetime.

Double free
This occurs when a value's destructor is run twice. This can happen when transmuting a borrowed value to an owned value. You should never do that.

Data race
This can happen when transmuting a shared reference to an exclusive reference. You should never do that.

Index out of bounds
Rust will usually prevent this and panic, but if an unsafe function such as is used, it can cause UB.

Wrong layout
When transmuting between values with incompatible memory layouts, UB can arise.