Why doesn't this closure outlive var?
Asked Answered
L

2

9

Consider the following Rust code:

use std::thread;

fn main() {
    bar();
    loop {}
}

fn bar() {
    let var = b"foo";
    thread::spawn(|| {
        write(var);
    });
}

fn write(d: &[u8]) {
    println!("{:?}", d)
}

To my understanding, var is on the stack of function bar, which no longer exists after it returns.

Still, the new thread accesses it afterwards and successfully writes the data.

  1. Why does this work?
  2. Why doesn't the Rust compiler complain?
Larousse answered 17/1, 2023 at 19:21 Comment(0)
T
8

To my understanding, var is on the stack of function bar, which no longer exists after it returns.

var is just a reference with type &'static [u8; 3]. This reference value is what is on the stack, not the string literal.

The owner of the byte string literal b"foo" is the program binary, which results in the string literal having a 'static lifetime because it exists for the entire lifetime of the running program.

Tanh answered 17/1, 2023 at 19:39 Comment(0)
P
4

The b"foo" value doesn't live on the stack actually. It is stored in the read-only memory of the compiled binary and has a 'static lifetime.

Consider this alternative example:

fn bar() {
    let var = format!("foo");
    thread::spawn(|| {
        write(&var);
    });
}

fn write(d: &str) {
    println!("{:?}", d)
}

That won't work (unless you add move before the closure), because var (of type String) is allocated on the stack.

Perrone answered 17/1, 2023 at 19:43 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.