Re:Mistakes to avoid with C++ 11 smart pointers
by millstone on Sunday May 15, 2016 @03:42AM
(#11699934)
Perhaps you consider this splitting hairs, but I would say this isn't the borrow checker at work, because nothing is being borrowed! Instead it's Rust's move semantics, which is separate from the borrow checker. We can envision C++ with no borrow checker, but Rust-style move-semantics-by-default, and it would be a better language for it.
An example of #11:
use std::cell::RefCell;
fn main() {
let c = RefCell::new(5);
*c.borrow_mut() = *c.borrow() + 1;
}
this is equivalent to * c = *c + 1, which is conceptually safe, but crashes at runtime in Rust.A real world example of this: say you are keeping a count of some event in a global or thread local storage. You pull out a mutable reference, so you can update the count more efficiently. You then call a function which accesses that global. Crash!
Rc/Arc have the same issue. This defeats the point of refcounting: it means you must have global knowledge of the refcount in order to reliably call mutating functions on the contents. But if you have that global knowledge, you wouldn't need refcounting in the first place!
Can you actually cause #11 in Rust? Example?
Circular references remain a problem, but they can only cause memory leaks, not security errors or crashes. It would be nice to have a Rust static analysis tool for circular references. Often, you can prove their absence for a type.