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.
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).
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.