Dangling reference question

Hi,
I've recently started studying Rust from the Book, currently at the end of Ch.4, and curious about some imaginary case on references.
Assume we have a thread, t1, that owns a String st. This thread creates other thread, t2, passing a reference to st as argument. Then t1 terminates, dropping st (because it owns it) but t2 continues to execute. Has the reference become a dangle?

Not likely. Creating a reference (for t2 argument) must again increase reference counter, and t1 termination wouldn't decrease it to 0, because this other reference above (gone from t1 to t2 as an argument) still lives. Only when t2 disposes of its reference (e.g. by terminating) will the reference counter reach 0, allowing the object to be dropped.

P.S.: of course, this is only valid for Sync objects which can have thread-shared references. These handle the reference counting threadsafe, so the String should probably be wrapped into some Sync container. For a non-Sync, it is mostly an error to pass the reference at all.

Reference that could become dangling can't be passed into thread, in the first place.

To be sent into thread, reference must be either 'static - that is, the object it references must be valid until the program termination - or hidden behind the reference counter (or, more precisely, atomic reference counter). In your case this is not satisfied, and borrow checker will immediately remind you of this - check this playground, for example.

2 Likes

In std, the std::thread::spawn function will require you to specify a lambda with 'static lifetime, which means that you cannot pass a reference to something that will possibly dangle. The borrow checker will prevent you from passing a reference to a stack-owned String to the spawn() function.

The rayon library allows you to borrow from stack variables. It's sound because the implementation will block the current thread until the new thread terminates, so stack variables can't go out of scope while the new thread is running (see here).

6 Likes

Rust's references (&Foo) are not allowed to dangle in any situation at all, and this will be enforced at compile time. In Rust code not marked as unsafe nothing can break it, and you should rely on them never dangling.

Even in unsafe blocks existing references are guaranteed not to dangle. The only place where it can break down is if unsafe code makes a new invalid reference. It's still not supposed to do that (that would be a bug), but unsafe block has power to do as much as any code in C.

But all Rust code you interact with is supposed to always give you safe to use references in all cases, and you never have to worry about them becoming dangling.