top | item 40788188

(no title)

dureuill | 1 year ago

> no raw loops and not raw pointer access

- Do these rules allow iterators?

- Under the "no raw pointer" rule, how do you express view objects? For instance, is `std::string_view` forbidden under your rules? If no, then you cannot get rid of memory issues in C++. If yes, then that's a fair bit more than "no raw pointer access", and then how do you take a slice of a string? deep copy? shared_ptr? Both of these solutions are bad for performance, they mean a lot of copies or having all objects reference-counted (which invites atomic increment/decrements overhead, cycles, etc). Compare to the `&str` that Rust affords you.

- What about multithreading? Is that forbidden as well? If it is allowed, what are the simple rules to avoid memory issues such as data races?

> That's already available in well written C++

Where are the projects in well-written C++ that don't have memory-safety CVEs?

discuss

order

jpc0|1 year ago

You are actually just arguing for the sake of arguing here.

Rust bases all their data structures on pointers just like C++ does, just because you cannot look behind the curtian doesn't mean they aren't there with the same issues. Use the abstractions within the rules and you won't get issues, use compiler flags and analyzers on CI and you don't even need to remember the rules.

And of the billions of lines of code are you really going to try to argue you won't find a single project without a memory safety CVE? You will likely find more than there are rust projects in total, or are we going to shift the goalposts and say they have to be popular, then define popular and prove you won't have a memory safety issue in a similarly sized Rust project. Shift the goalposts again and say "in safe rust" but then why can I not say "in safe C++" and define safe C++ in whatever way I want since the "safe" implementation of rust is defined by the Rust compiler and not a standard or specification and can change from version to version.

I've agreed already that Rust has decent use cases and if you fall into them then and want to use Rust then use Rust. That doesn't mean rust is the only option or even the best one by some measure of best.

dureuill|1 year ago

> You are actually just arguing for the sake of arguing here.

I'm very much not doing that.

I'm just really tired of reading claims that "C++ is actually safe if you follow these very very simple rules", and then the "simple rules" are either terrible for performance, not actually leading to memory safe code (often by ignoring facts of life like the practices of the standard library, iterator and reference invalidation, or the existence of multithreaded programming), or impossible to reliably follow in an actual codebase. Often all three of these, too.

I mean the most complete version of "just follow rules" is embodied by the C++ core guidelines[1], a 20k lines document of about 116k words, so I think we can drop the "very very simple" qualifier at this point. Many of these rules among the more important are not currently machine-enforceable, like for instance the rules around thread safety.

Meanwhile, the rules for Rust are:

1. Don't use `unsafe`

2. there is no rule #2

*That* is a very very simple rule. If you don't use unsafe, any memory safety issue you would have is not your responsibility, it is the compiler's or your dependency's. It is a radical departure from C++'s "blame the users" stance.

That stance is imposed by the fact that C++ simply doesn't have the tools, at the language level, to provide memory safety. It lacks:

- a borrow checker

- lifetime annotations

- Mutable XOR shared semantics

- the `Send`/`Sync` markers for thread-safety.

Barring the addition of each one of these ingredients, we're not going to see zero-overhead, parallel, memory-safe C++. Adding these is pretty much as big of a change to existing code as switching to Rust, at this point.

> Use the abstractions within the rules and you won't get issues, use compiler flags and analyzers on CI and you don't even need to remember the rules.

I want to see the abstractions, compiler flags and analyzers that will *reliably* find:

- use-after-free issues

- rarely occurring data races in multithreaded code

Use C++ if you want to, but please don't pretend that it is memory safe if following a set of simple rules. That is plain incorrect.

[1]: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines