Rust Safety Is Not Superior to C++, Bjarne Stroustrup Says – Slashdot
developers.slashdot.org
developers.slashdot.org
https://security.googleblog.com/2022/12/memory-safe-language...
While C++ with the latest features should be secure enough in theory, in practice practically no one is using all the latest features just right to achieve the needed security.
Sorry, the NSA report is correct. Using C or C++ opens your project up to memory safety risks. Use a memory safe language if at all possible.
That is provably false:
https://www.joelonsoftware.com/2000/04/06/things-you-should-...
There are numerous developers on this forum who could provide eyewitness accounts of project rewrite horror stories.
The same thing would happen if you rewrote in rust.
However, there are some patterns that Rust does not allow that other languages do allow which may help to avoid problems.
For example, creating cyclic dependencies and relationships is more difficult in Rust due to the way that ownership rules are enforced. Rust also helps to avoid data races and memory unsafety issues so that whole classes of errors and bugs can be avoided.
You're confusing things. Google's example focused on rewriting specific components with a specific goal in mind: fix/avoid unsafe memory access. The examples in that blog post consist of major rewrites of huge software projects like browsers, whose goal was to be feature complete.
Those are quite different things.
The statement, "Almost every project sees fewer issues with a rewrite, no matter which languages are involved.", was too broad and I wanted to show how I disagreed with it when the article I cited was concerned with component rewrites.
I did not intend to conflate the two since the scopes are quite different.
I would personally choose Rust over C++. I dislike the number of gotchas that C++ has and I think the language has gotten too big and complex to use safely.
In the article I linked above, the Google Android team stated:
"To date, there have been zero memory safety vulnerabilities discovered in Android’s Rust code."
Their C++ code requires more static analysis tools and fuzzers and does not have a comparable record.
If modern C++ were as safe as Rust then why wouldn't they just use modern C++? It would be a lower effort rewrite and would not need new compilers.
This take sounds like fomo mixed with cargo cult programming.
When you write something in C++, nothing forces you to use all features of C++. There is no bingo card you have to fill to get your project to compile. You just pick the things you feel serves your purposes, and stick with them.
I don't really understand this irrational take. It's like claiming they don't want to speak in English because the dictionary is too large and some words are too tricky to spell to use in a conversation.
It's not irrational to want to avoid trouble.
Why would I want to use C++ with its plethora of gotchas, traps, caveats, pitfalls and footguns when I can use something safer and just as performant?
Why stop at smart pointers?
I would rather use a smarter compiler / smarter language with fewer gotchas, traps, caveats, pitfalls and footguns.
> In particular, the work on the C++ Core Guidelines specifically aims at delivering statically guaranteed type-safe and resource-safe C++ for people who need that without disrupting code bases that can manage without such strong guarantees or introducing additional tool chains
Tells me he doesn't really "get it." People do not follow the core guidelines, and other languages are designed such that there aren't guidelines. There's a type checker (wave hands here) that proves your code and its dependencies are memory safe (within some sane definition).
Another thing worth mentioning is that "type safety" isn't something other languages need to worry about since it's generally not possible to tell a type checker that it's wrong.
https://twitter.com/m_ou_se/status/1615736570400890883?s=20&...
At least some people screenshot the original.
This seems like it's split between compiled and interpreted languages, no? Typescript and Python (I believe) will let you override types in their type system, I assume because doing so has no effect on the underlying code. I'm assuming that compiled languages with integrated type-checkers actually use the type checker for allocations so changing types has runtime implications.
E.g. Typescript doesn't care if you use `as` to force the type of a variable because it has no impact on the runtime. Javascript will create objects and allocate memory the same regardless of what Typescript thinks the type is. That's not true of something like Go, where changing the type of a variable would require different allocations and changing a struct to a string would break low-level features like GC.
There's also a sliding scale of "weak" to "strong" typing (I don't want to attempt to define it). C is the canonical example of a "weakly" typed languages, but imo C++ fits that as well - unless you follow the idioms of "type safe" programming, which makes it difficult for a programmer to write code that is not type checked. The difference between a weak-but-statically typed language and dynamically typed language is that it's possible for a programmer to write code that is never type checked, leading to potentially undefined behavior. C++ needs a notion of "type safe" programming because it is possible for a programmer to write such code. Contrast to a language like Rust or Haskell, where it's close to impossible to write type-unsafe code (without explicitly saying you want to).
My point is that implying "safe" programming also implies type safety misunderstands that such safety is close to meaningless in safe programming languages. It's just so much harder to write type-unsafe code it's kind of pointless to bring it up, unless you're writing C and C++.
I don't think this is true at all. There are already a few popular static code analyzers and lingers around which integrate quite nicely with your run of the mill build system.
The purpose of these static code analyzers and linters is none other than enforce the adoption of stuff like the C++ core guidelines in a workflow a kin to unit testing.
How do you explain that, based on your personal assertion that no one bothers with those? I mean, even popular C++ IDEs support those out-of-the-box.
I really do not understand this absurd idea that those who care about safety drop everything they're doing to mindlessly migrate all things under the sun to a programming language, and the only ones not doing that are the poor incompetent fools who foolishly don't succumb to this cargo cult nonsense.
Linting exists for C since 1979.
I've not worked with Visual C++ much (used it once and thought the CLI pointers were a cool feature, though), so maybe that's better. However, my experience on Linux has always been… Uncomfortable? I don't know what to call it.
Sure, all of these things kinda and almost work. Technically they make things marginally better. So, he's not wrong, but only by the strictest possible definition of "wrong". And Jesus Christ, they always made me feel like I stepped into a time machine and traveled back 30 years (and I'm only turning 30 this year), and induced so much friction into both set up and workflow.
Rust on the other hand? I don't have to think about it any of those, and it borrows (no pun intended) great FP type system features to boot.
Also, I don't know what went wrong with C++ Concept, but I was excited about them initially, and now I'm just underwhelmed by them. The coroutine stuff is also a bit frustrating.
C++ is a language that has jaded me with a thousand small frustrations over the years. I still have a small hope that it'll one day rebound (as I used to write it for a long time), but in the mean time I'll stick to Rust.
Also, since he's deliberately chosen to be petty about memory safety in Rust, it probably doesn't warrant addressing, but I'll take the troll-bait this time: nobody EVER said memory safety is the ONLY safety. Ever. I've not seen a single person make that claim, or tout Rust as a "safe" language. Memory safety DOES however eliminate a whole category of bugs (a lot of which can be security or stability bugs in real world environments). That's literally all there is to it.
Edit: my experiences predate a having a Cpp LSP that works (idk if that has changed in the last few years)
I love his talks, and how he tries to push the C++ community to write better code and less "C with C++ compiler" code style, however the production code I get to occasionally look into proves that a large majority just doesn't care.
Which is also visible in surveys like the ones published by JetBrains, where unit testing and static analsys tooling never get that high.
I don't agree, specially considering legacy code. Those of us still have to deal with an awful lot of code written 10 or 20 years ago still have to maintain code that juggles pointers and references around in ways that are hard to track ownership, and migrating this code to C++11 is no simple task. This doesn't mean people don't care. It just means the industry cannot afford getting whole teams to spend a couple of years on sabbatical to refactor legacy code and pay it's legacy debt.
This is perhaps the biggest strawman that Rust fanatics use to criticize all things that isn't written in Rust. They pick their small little greenfield modules and boast how safe and perfect it is, and proceed to criticize all legacy production code whose teams can't even spare time to fix long standing bugs, let alone pay off technical debt. And that's somehow something Rust fixes?
I also preach against "C with C++ compiler" since around 1994.
Plenty of time for people to adapt on how to write proper, safer C++ code than using C idioms.
See, this is yet another instance of the strawman argument I pointed out.
This is not a "enough time" problem. It's a resource allocation problem. Time is irrelevant if no resources are allocated to a task. Rust does not add manpower to rewrite things.
Rust fanatics just perpetuate survivorship biases because the project they did with the express purpose of fixing a specific issue ended up fixing the specific issue, and proceed to somehow go the cargo cult way and praise the framework instead of the rewrite effort. It's disingenuous and a gross misrepresentation of reality, and one which will inevitably come around to bite Rust in the ass. We already see backpedalling with regards to some of these claims once Rust started showing up in SVEs.
Of course there are exploits in safer systems languages, memory corruption issues and arithmetic exploits only represent 70% of root causes.
We still need to consider the remaining 30%.
Another benefit of Rust is that you can largely avoid the same category of monster codebases common in C++, because there's much less (virtually none) friction in splitting up your codebase into crates.
Like SURE... You CAN do this in C++, but it's usually just simply not worth the bother, because you gain next to nothing
In part, I think the issue you described is that usually with C++, the correct solution is the more obscure one, and usually much longer and sometime even harder to parse (by a human), while the incorrect (or less correct) solution seems idiomatic and obvious.
I think this would probably not have been an issue if the language shed baggage as it evolved.
If is were possible to use a language subset (C++ indigo or something like that) that only allowed a certain subset it (along with toolchain support) would help since at least new projects and libraries could strictly conform to that. Similarly old code bases could be migrated over time.
I think this is the real value. As an analogy, I once updated a large legacy codebase from Java 1.x (pre-generics) to Java 1.5+ adding generic annotations everywhere. It took many months of incremental, interspersed work. In the end, there was exactly 1 bug uncovered where a drop-down list would rarely show `ObjectType@addr` instead of the proper rendering which was otherwise harmless.
This is to say that the added type information wasn't mainly needed to reduce bugs as it's raison d'etre, but that it meant that developers had reduced cognitive load of types while working.
(For the record: I’m a lifelong C/C++ programmer who has written large systems in it)
> There is not just one definition of "safety", and we can achieve a variety of kinds of safety
I agree, but C++ and Rust both fail at what I could consider a major form of safety not too far below memory safety. It might be called “capability safety” or “effect safety”: a function call should not be able to have side effects or read data outside that explicitly permitted by the caller (or importer or program manifest or whatever). I would consider a form of “unsafe”-like escape hatch acceptable so long as using that escape hatch is itself treated as a capability.
Rust and C++ don’t do this at all, although I could imagine it being retrofitted into Rust or a similar language. Java sort of tried, and it was a near complete failure on many counts. Several experimental languages have this as an explicit goal.
Some container and VM systems attempt this sort of security. Sandstorm was a notable example.
I like the idea in theory, but depending on how it's implemented at the language level, it could end up being a bit hit or miss.
https://github.com/austral/austral
Deno does something along these lines too. WASM does, too, if you squint hard at it.
It would be nice to see some version of this in Rust too
It would be nice to see some version of this in Rust too
If Bjarne put something akin to Rust's Editions in C++, and regularly removed poor designs, then yes C++ would be pretty close to Rust for new projects.
https://github.com/cplusplus/papers/issues/631#issuecomment-...
Not that that means you're strictly wrong, mind you, just that only textual inclusion issues and template issues were voted on as being blocking at that time.
If you ctrl-f "rust" in this PDF, there are zero hits.
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p27...
This is the one that had a ton of discussion over the last few days.
The one you linked from the /. article is much, much shorter, and has only Bjarne as the author, unlike the other, which has co-authors.
I never liked these crummy /. mini-writeups that may or may not be accurate.
https://twitter.com/m_ou_se/status/1615736570400890883?s=20&...
People are emotional creatures; I'm sure Bjarne is no exception. I find it hard to fault them too much it, especially as I'm not so confident I'd do any better in similar circumstances, and I've seen others do a lot worse under similar circumstances. C++ isn't going to vanish any time soon no matter what, so it's good people keep working on it – a few misguided comments here or there? Meh.
But if you wanna write safe code, from scratch, because you don’t want to recycle your dangerous old C++ codebase; then why would you write that new code in C++ when rust is ready and here to do it?
https://devblogs.microsoft.com/cppblog/high-confidence-lifet...
is modern c++ so complex, big with a huge surface area to shoot yourself, yes.
that's the problem with C++ it's such a huge language that knowing to do the right thing is difficult.
Right, but is it still possible to write bad, unsafe, inefficient C++ that looks indistinguishable from the safe kind?
"Do you develop on GitHub? You can keep using GitHub but automatically sync your GitHub releases to SourceForge quickly and easily with this tool so your projects have a backup location, and get your project in front of SourceForge's nearly 30 million monthly users. It takes less than a minute. Get new users downloading your project releases today!"
SourceForge: from de-facto standard open source tooling to "please allow us to mirror your GitHub".
But I remember having off-by-one errors doing just that in basic for-loops in C++.
> I envision compiler options and code annotations for requesting rules to be enforced. The most obvious would be to request guaranteed full type-and-resource safety.
You'd think someone that worked on a compiler for decades would come to the realisation that opt-in safety is just dumb. You want everything to be safe by default, despite the performance implications, and then allow programmers to peel back safety features explicitly where they are not needed.
You don't buy a gun and the safety lock as an add-on.
Borrowing from Donald Norman and his Design of Everyday Things book, safe programming in C and C++ relies too much on "knowledge in the head" instead of "knowledge in the world" in order to do it correctly.
You don't need the big borrow-checker hammer from Rust to be a lot better. Most CVEs (memory safety related) are about out-of-bounds writes/reads. You could mitigate a huge chunk of those problems by just doing something as sensible as having a well defined concept of slices with bounds checking turned on by default.
But this seems to elude the C and the C++ committee for some weird reason.