4 ms·
>We need to move forward to Rust In fairness, C++ containers know their size. And Rust's solution to buffer overflows is the same as every other language — run
by acconsta 11y ago
>We need to move forward to Rust
In fairness, C++ containers know their size. And Rust's solution to buffer overflows is the same as every other language — run time bounds checking.
- icholy 11y agoCan't you turn them off though?
- steveklabnik 11y agoNot with a flag or anything. As said above, if you use iterators, it's not generally an issue, or you can call an unsafe function that doesn't do the check.
- kibwen 11y agoYou can opt out of bounds checking by using the unsafe `get_unchecked` method instead of the array indexing syntax. There's no compiler flag to turn off bounds checking, because the language doesn't want to encourage memory safety that's dependent only on compiler flags (and also because the cost of runtime bounds checking in real programs is indistinguishable from noise).
- acconsta 11y ago>the cost of runtime bounds checking in real programs is indistinguishable from noise Can you show us the benchmarks for that?
- kibwen 11y agoThe source of my assertion comes from repeated conversations with the Servo developers, who have written many hundreds of thousands of lines of Rust in a project whose goal is to be twice as fast as modern web browsers (in other words, they are comparing themselves to programs written in C++, and speed matters). They regularly profile in pursuit of tracking down inefficiencies, and bounds checking has never been even a blip on their radar. Quotes from the exchange I've had just now with pcwalton: "I haven't done rigorous benchmarking but I have never seen it in instruction level profiles [...] I'd rather just spend my time shipping software that uses fast bounds checks and prove it that way :) [...] my point is simply that the delta between idiomatic Rust code that uses iterators and no bounds checks and the idiomatic Rust code that uses iterators and bounds checks is incredibly small since bounds checks are so rare to begin with" (http://logs.glob.uno/?c=mozilla%23servo#c271807 http://logs.glob.uno/?c=mozilla%23servo#c271807) As for actual benchmarks, I think they would actually be quite easy to produce. There's exactly one line in the Rust stdlib that provides bounds checking for indexing, right here: https://github.com/rust-lang/rust/blob/master/src/libcore/slice.rs#L552 https://github.com/rust-lang/rust/blob/master/src/libcore/sl... . All you would need to do is take out that line and compile Servo with your modified stdlib and compare the results of running the built-in benchmarks. I may just do this myself as a blog post. :)
- deleted 11y ago[deleted]
- acconsta 11y agoOK, data definitely helps. It's not always easy to predict what modern CPUs will do! For the record, there seem to be a lot of bounds checking independent of indexing: https://github.com/rust-lang/rust/blob/master/src/libcollections/vec.rs#L471 https://github.com/rust-lang/rust/blob/master/src/libcollect... https://github.com/rust-lang/rust/blob/master/src/libcollections/vec.rs#L471 https://github.com/rust-lang/rust/blob/master/src/libcollect... https://github.com/rust-lang/rust/blob/master/src/libcollections/vec.rs#L471 https://github.com/rust-lang/rust/blob/master/src/libcollect... https://github.com/rust-lang/rust/blob/master/src/libcollections/vec.rs#L471 https://github.com/rust-lang/rust/blob/master/src/libcollect...
- kibwen 11y agoYou just linked to the same line four times. :P
- acconsta 11y agoOh, oops. 471, 508 679, 766.
- kibwen 11y agoGiven that these are all achieved with the `assert!` macro, we can fortunately just redefine the macro to be a no-op in order to determine the runtime cost of all assertions in the standard library (note that assertions that aren't required for memory safety should already be using the `debug_assert!` macro, which is in fact compiled to a no-op in non-debug builds). This will overestimate the impact of removing bounds checks (since we'll potentially be removing lots else as well), but I'm curious to see if the performance impact will still be negligible regardless.
- acconsta 11y ago
- wspeirs 11y ago> And Rust's solution to buffer overflows is the same as every other language — run time bounds checking. Right, because that's the only way to do it? What's wrong with that? The point is a language like Rust has built-in bounds checking...
- okasaki 11y agoSo does C++: http://www.cplusplus.com/reference/stdexcept/out_of_range/ http://www.cplusplus.com/reference/stdexcept/out_of_range/
- acconsta 11y ago>The point is a language like Rust has built-in bounds checking... As does C++. See e.g. vector.at and libstdc++ debug mode: https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.h... The difference is only opt-in vs. opt-out. To its credit, Rust provides additional protections against iterator invalidation and dangling pointers, but its approach to buffer overflows is the same.
- Animats 11y agoThe trend is towards optimizing out bounds checks for at least the easy cases, such as FOR loops. Go does this. Rust should, and probably will soon. That tends to get most of the inner loops where it really matters, like a matrix multiply. C++ can't do that because the compiler doesn't know that a template-implemented bounds check is a bounds check. Also, in C++ containers, ".at()" is usually checked, but "[]" is not. So C++ code still regularly has buffer overflow problems.
- logophobia 11y agoRust does optimize iterators, just not random access. You can even turn off the bound checks with get_unchecked, if you really really need unchecked random access.
- steveklabnik 11y ago
- nostrademons 11y agoMost of the time, you'll be accessing Rust collections through iterators, and iterators fold the bounds-check into the termination condition. There's no additional overhead here; it compiles into the exact same code that the C would.
- acconsta 11y agoIf you're using iterators, you don't have to worry about buffer overflow. But every A[i] random access needs to be bound checked.