Static variable

From Rust Community Wiki
Jump to navigation Jump to search

See also: Reference – static items

Static variables, also called global variables, are items that contain a value that is always accessible; it is never created or destroyed. Static variables can have a destructor, but that destructor is never run.

Unlike constants, static variables have a fixed memory location. Their initial value is const-evaluated at compile time and has a 'static lifetime.

A static variable can be declared within a function, which makes it inaccessible outside of the function; however, this doesn't affect its lifetime (it isn't dropped at the end of the function).

Limitations[edit | edit source]

Static variables must be thread safe. This means that their type must implement the SyncThis links to official Rust documentation trait. For example, RcThis links to official Rust documentation or RefCellThis links to official Rust documentation can't be used in a static variable as they are not thread safe - having multiple threads access them at once causes a data race.

Static variables can refer to other static variables, but only through a reference, not by value.

Constants can't refer to a static variable.

Example[edit | edit source]

fn get(n: usize) -> &'static str {
    static STRS: &[&str] = &[
        "zero", "one", "two", "three", "four",
        "five", "six", "seven", "eight", "nine",
    ];
    STRS[n]
}

Using statics or constants[edit | edit source]

It can be confusing whether or not you should use a constant item or a static item. Constants should, in general, be preferred over statics unless one of the following are true:

  • Large amounts of data are being stored
  • The single-address property of statics is required.
  • Interior mutability is required.

Mutable static variables[edit | edit source]

Static variables can be mutable. Since Rust can't prove the absence of data races when accessing a static mutable variable, accessing it is unsafe.

Using static mutable variables is discouraged, since they are not only unsafe, but also very difficult to use correctly: Without synchronization primitives such as MutexThis links to official Rust documentation, it is almost impossible to prove that no data races occur. They are likely to be removed in a future version of Rust; if you need unsafe static mutability use UnsafeCellThis links to official Rust documentation.

Example[edit | edit source]

static mut FOO: i32 = 40;

pub fn add_two() -> i32 {
    unsafe {
        FOO += 2;
        FOO
    }
}

Note that this is unsound: If add_two() is called from multiple threads, the access of FOO is racy.

A solution is to use a synchronization primitive such as Mutex<i32>This links to official Rust documentation or AtomicI32This links to official Rust documentation. Since these have interior mutability, we can use a safe, immutable static variable:

static FOO: AtomicI32 = AtomicI32::new(40);

pub fn add_two() -> i32 {
    let prev = FOO.fetch_add(2, Ordering::SeqCst);
    prev + 2
}