6 ms·
C++ does bring memory safety, but relies on best practices being followed to do so. Rust is actually heavily influenced by C++, but enforces that those practic
by mgaunard 5y ago
C++ does bring memory safety, but relies on best practices being followed to do so.
Rust is actually heavily influenced by C++, but enforces that those practices are respected as part of the language.
- varjag 5y agoI'm really sorry but memory safety reliant on best practices is not memory safety.
- mumblemumble 5y agoIt's long been done fairly successfully in business domains like aerospace and firmware development. Where I'm less convinced that it's an option with a high likelihood of success is in open source. It's one thing when you've got a $250,000 salary riding on you ability to scrupulously follow best practices. But results may vary when the work is being done on an amateur basis.
- varjag 5y agoI'm doing embedded development day and night, so am aware how prolific C is. That however does not make it memory safe. 'Best practices' really means using humans as compiler preprocessors and hedges on humans being infallible.
- xxpor 5y ago>you've got a $250,000 salary riding on you ability to scrupulously follow best practices Sounds like a great way to have a toxic workplace that either yells at people for bugs, or never gets anything done because people are paranoid about committing bugs (or both!). Meanwhile, with a different language you get the compiler yelling at you instead. Automated enforcement uber alles. I don't think open source vs commercial dev really matters that much.
- adwn 5y ago> But results may vary when the work is being done on an amateur basis. Much, if not most, of Linux kernel development is done by employees of various companies, who are being paid for their work. Typically, that's in the form of device drivers, which also happens to be where I've seen the shoddiest, buggiest code in the kernel [1]. [1] Think "driver A abusing the 'private' pointer of driver B for its own purposes" kind of buggy.
- Too 5y agoIf by successful you mean where changing one line of code takes 2 weeks of change request, 2 weeks of requirement analysis, 2 weeks of system specification translation, 2 weeks of test specification, 2 weeks of test case implementation, 1 day of implementation and finally 2 weeks of code review, and so on. Then yes, you are completely right. In aerospace you probably want all this anyway, but for others, where 99.99% is enough, there needs to be a cheaper and more efficient way.
- gravypod 5y agoRust also relies on best practices. It is best practice not to use `unsafe` blocks unless absolutely needed. That does not mean Rust is an unsafe language.
- Cyph0n 5y ago1. The corollary is that code that does not contain unsafe code is guaranteed to not contain memory safety bugs, assuming that you trust and/or have audited unsafe usage in your dependencies. 2. unsafe blocks are explicit and therefore visible during code review. Memory safety violations in C++ are not always visible, simply because they are implicit. 3. Thanks to (2), unsafe usage in a codebase can be easily quantified and, if needed, audited.
- mgaunard 5y agoViolations to the C++ best practices that enforce memory safety are definitely visible during code reviews. The harder problem is convincing people that raising their quality standards is a necessary requirement for them to contribute to the code.
- Cyph0n 5y agoFirstly, the difference I was trying to emphasize is "guaranteed to be visible due to the unsafe keyword" vs. "potentially not visible". Secondly, quality standards rely on the human element, which we know is fallible and never 100% reliable. Compiler-enforced memory safety checks are (in theory) infallible[1]. [1]: Infallible when all of your dependencies are also verifiably memory safe. In reality, this is not the case, but I believe that Rust can reliably get much closer to 100% than usual.
- nineteen999 5y ago> 1. The corollary is that code that does not contain unsafe code is guaranteed to not contain memory safety bugs, assuming that you trust and/or have audited unsafe usage in your dependencies. Doesn't this assume that there are no bugs in the Rust compiler (for "safe" code)? Isn't that still somewhat of a big assumption at this point? I get that is indeed a very core goal of Rust, but has this been proven for any/all released versions of the Rust compilers?
- smoldesu 5y agoEnsuring memory safety in C++ is an endless game of spinning plates. It's possible, but the "best practices" for doing so certainly don't feel like best practices. I've watched people repeatedly compile a program, changing a single line and running it through Valgrind for hours on end. With Rust, you actively have to fight the compiler to cause memory leaks. Addendum: yes, that last line is what pisses a lot of people off with Rust, and honestly, rightfully so. I've written quite a bit of Rust by now, and getting your code to work can feel like a bit of an escape room. Having C as an option on the kernel alongside it is a great idea though, because there are situations where I'd happily pick up C over Rust, and they're not just 'edge cases' where Rust falls short. Ideally, they're two different tools that can be applied depending on the situation at hand.
- mgaunard 5y agoIf you correctly model ownership with RAII, which also enforces strong class invariants, and make sure all operations satisfy basic exception safety, then leaks are not possible. Those are the most elementary rules that one must follow when writing C++.
- bcrosby95 5y ago> If you correctly model ownership Doing something correctly is not a best practice though. If it were, we could just say "if you correctly manage memory". What happens when you mess up? What happens if you incorrectly model ownership with RAII? Or is it not really possible?
- deleted 5y ago[deleted]
- int_19h 5y agoObject graphs where there's no clear owner are not automatically "incorrect" - whatever they're modelling might be non-hierarchical itself - yet would result in a leak without a GC.
- j16sdiz 5y agoC++ also bring implicit memory allocation. This is a big no for kernel. When rust was proposed for linux, controlled memory allocation was on the top of requirements list
- varajelle 5y agoWhat implicit memory allocation are you talking about?
- mgaunard 5y agoThe only thing I can think of that allocates is throwing an exception (nad that's an ABI-specific strategy), but I doubt that's what he means.
- woodruffw 5y agoThey might be referring to how easy it is to accidentally/unwittingly invoke the copy constructor in C++. `Foo x = Foo();` used to be the famous example of that, although more recent versions of C++ may guarantee that the copy is elided there. Another good example is implicit comparison conversions, e.g. some class defines `operator==` as non-explicit and any code that does `x == y` where `typeof(x) != typeof(y)` may find itself going though a possibly-allocating constructor.
- int_19h 5y agoAllocations in this context usually refers to heap allocations. Temporaries aren't heap-allocated.
- woodruffw 5y agoTemporaries may or may not be heap-allocated; the C++ spec doesn't specify. But even beyond that: you can have a non-trivial constructor that requires heap allocations internally. So even relying on (sane) compiler-defined behavior won't save you in the general case.
- rcxdude 5y ago'best practices' for memory safety in C++, even modern C++, are still so convoluted as to not be reliably followable in practice, either by humans or humans assisted by static analysis.
- mgaunard 5y agoThey are exactly the same practices that Rust has built-in into the language, so I'm not sure what you're hinting at.
- sanxiyn 5y agoIn theory, C++ programs use std::optional, just as Rust programs use std::option. In practice, such C++ programs are extremely rare, whereas such Rust programs are majority.
- nicoburns 5y agoThere's an even clearer example here: dereferencing a C++ std::optional is undefined behaviour. Dereferencing a Rust std::Option is a compile time error.
- pjmlp 5y agoIn theory, in practice when using debug libraries, undefined becomes defined as a runtime check that will lead to an assertion error, or a static analyser failure. https://godbolt.org/z/re51ensMe https://godbolt.org/z/re51ensMe terminate called after throwing an instance of 'std::bad_optional_access' what(): bad optional access Naturally not everyone goes by adopting best practices, so there is that.
- Quekid5 5y agoThey're saying that the Rust compiler will reliably enforce these things... and that it's completely trivial to surface any cases where the programmer thinks that they are smarter than the compiler, e.g. for extra code review, outright rejection, etc.