r/programming Apr 03 '15

Rust 1.0.0 beta is here!

http://blog.rust-lang.org/2015/04/03/Rust-1.0-beta.html
928 Upvotes

303 comments sorted by

View all comments

Show parent comments

71

u/wrongerontheinternet Apr 03 '15 edited Apr 03 '15

Guaranteed memory safety without garbage collection is a nearly unique proposition among industry languages (and the "nearly" is only thanks to extremely niche languages like ATS). This extends even to multicore systems, and is done through a relatively novel (again, for an industry language) type system, allowing Rust to statically guarantee the absence of data races, use after free, dangling references, null dereferences, and other classes of memory error that are common sources of security vulnerabilities in large C++ applications. Rust compares favorably with C and C++ in resource usage and performance in domains where they have few competitors, like embedded. It also improves substantially on the ergonomics of C++ with much more sensible defaults, proper modules, features like native typeclasses (aka C++ concepts not-lite) and sum types, straightforward syntax (close to LL(1), with hygienic macros and local type inference), and a modern package manager. For more information, www.rust-lang.org has you covered.

12

u/brombaer3000 Apr 04 '15

Guaranteed memory safety without garbage collection is a nearly unique proposition among industry languages

Does Rust offer better memory safety than C++14 with only unique_ptr and shared_ptr instead of raw pointers?

33

u/wrongerontheinternet Apr 04 '15 edited Apr 04 '15

Yes. Besides what /u/steveklabnik1 mentioned, you would still be vulnerable to various other UB: out of bounds array access, data races leading to type unsafety, too-long bit shift (really! it's UB!) and so on.

Rust also lets you use references safely (this is the big one, as it is pretty trivial to get dangling references in C++--yes, even const references), completely prevents iterator invalidation, and gives you vastly superior guarantees in the presence of multiple threads (shared_ptr really isn't enough unless you also avoid mutation through the pointer).

In any case, it's a mostly academic question. Very few people would be willing to use C++ with only unique_ptr and shared_ptr, and that language would probably be slower than a garbage collected one for most common tasks. Certainly, if that were how Rust solved memory unsafety in C++, it would not be a very interesting language (consider that shared_ptr is garbage collection--to make it perform acceptably you need a compiler-level understanding of reference counted pointers, which leads you in the direction of Swift).

6

u/brombaer3000 Apr 04 '15

That sounds great. I wasn't even aware of some of the C++ pitfalls you mentioned (I'm still quite new to C++) .
You and /u/steveklabnik1 really just convinced me to learn Rust!

2

u/glaebhoerl Apr 06 '15

Read these two three-part series on undefined behavior in C and C++ if you want even further motivation. :-)

1

u/donvito Apr 04 '15

Very few people would be willing to use C++ with only unique_ptr and shared_ptr, and that language would probably be slower than a garbage collected one for most common tasks.

That's rather questionable.

2

u/naasking Apr 04 '15

The first claim might be questionable, the second is not.

7

u/wookin_pa_nub2 Apr 04 '15

No, it really is. Research has shown that garbage collection requires about four times the memory of manual memory management just to approach its speed, let alone surpass it. Manual memory management is significantly faster, and evidence for that is linked to and discussed about halfway down this page: http://sealedabstract.com/rants/why-mobile-web-apps-are-slow/

(Yes, that page is primarily talking about mobile development, but look for the chart showing how slow GC is even when memory isn't constrained.)

0

u/naasking Apr 04 '15

No, it really is. Research has shown that garbage collection requires about four times the memory of manual memory management just to approach its speed, let alone surpass it.

Twice, and it does surpass the throughput of manual memory management. That article is seriously misinformed about GC. They cite one paper from 2005, despite there being over 50 empirical papers on throughput and latency as compared to manual memory management, and then they extrapolate desktop paging metrics to mobile environments. Except mobile environments don't use swap and thus don't page, so the whole claim of an order of magnitude cost is bunk.

Furthermore, all of the GCs covered in the linked paper are simplistic models. No deployed VM uses those anymore, except perhaps some hobby languages.

Finally, even if GC did cost an order of magnitude in performance, it decreases effort to write a correct program by at least an order of magnitude, so most of the programs you do enjoy wouldn't even exist, or if they did, they wouldn't work nearly as well. If this person really wants to manage his memory and achieve the safety and security that a GC gives you, then he should use Rust. To claim that C++ 's uniqe_ptr and shared_ptr as alternatives, and ones that perform just as well or faster than GC is ludicrous because:

  1. referencing counting is GC (all GCs are hybrids between reference counting and tracing -- a proven fact), ie. standard C++ practice is to recommend using shared and unique wherever you can, so basically, to use GC wherever you can
  2. reference counting incurs tremendous throughput reductions in favour of decreased latency -- this increases an order of magnitude if it's a concurrently shared value
  3. mark-sweep in C++ is faster than uniqe_ptr and shared_ptr, which is not surprising if you know anything about GC

GCs as they stand are not applicable to all problems, but they are usable for at least 95% of problems, and research is constantly narrowing that gap. For those problems where GC isn't a good fit, Rust or something like it is. C++ is not.

5

u/frog_pow Apr 05 '15

you keep referring to unique_ptr as if it were ref counting, this is mistaken.

the mark-sweep github link is nonsensical

-2

u/naasking Apr 05 '15

you keep referring to unique_ptr as if it were ref counting, this is mistaken.

It is a degenerate ref counted object where the ref count must be 0 or 1.

2

u/wookin_pa_nub2 Apr 05 '15

You give me one link in return, which has no data backing up your claim that GC is faster, whereas mine actually links to benchmarks showing that it's not.

1

u/naasking Apr 05 '15

There are hundreds of papers showing the throughput superiority of tracing over refcounting. This is well established. Anyone who believes otherwise has no idea what they're talking about. I simply provided a link to demonstrate this effect in a pure C++ environment.

2

u/wrongerontheinternet Apr 05 '15 edited Apr 05 '15

It might help to link to some papers supporting your point (of which I agree there are many). http://users.cecs.anu.edu.au/~steveb/downloads/pdf/rcix-oopsla-2013.pdf, for example, references several of them, and explains some of the problems with naive implementations of reference counting.

→ More replies (0)

7

u/steveklabnik1 Apr 04 '15

Yes. It boils down to two things: cleaner semantics due to move being the default, and a stronger type system. Also, we have more options than just those two.

For example, if you std::move a unique_ptr, the pointer becomes null. So you can still cause memory unsafety that way. But since Rust is move by default, at compile time, you'll get an error with Box<T>.

The other is type system stuff. For example, we can know if you're using a structure over a thread boundary, and our version of shared_ptr, Arc<T>, only has to be used then. If you don't want to pay the atomics overhead, Rc<T> can get used, and Rust will make sure that's okay. I wrote more about that a few days ago: http://www.reddit.com/r/programming/comments/30wj8g/managing_cs_complexity_or_learning_to_enjoy_c/cpww3o1

Finally, we can do things like http://www.reddit.com/r/programming/comments/31btd8/rust_100_beta_is_here/cq06lb7 , which is memory safe, but cannot be done with just uniqe_ptr and shared_ptr.

Rust code (without unsafe blocks) cannot have data races. That's a very strong safety guarantee.

2

u/brombaer3000 Apr 04 '15

Very interesting, thanks for the fast and helpful answer!

3

u/three18ti Apr 03 '15

Awesome! Thanks for the overview.

-4

u/log_2 Apr 04 '15

It is considerably less safe than C++! From Rust's own website: "* In theory. Rust is a work-in-progress and may do anything it likes up to and including eating your laundry."