Bjarne Stroustrup's Plan for Bringing Safety to C++
thenewstack.io
thenewstack.io
The good: I see a new Stroustrup. At the time of the NSA report, he seemed to be in denial about the position C++ was in, security wise. The 'just be carefull'- wont-scale slide seems a much better basis to start the discussion from.He seems to propose something similar to rust editions, allowing problematic parts of the language to be switched off, with an escape hatch similar to unsafe.
If this would work out, rewrite it in rust could no longer be needed. There is an upgrade path for C++, and an incentive to use it.
The bad: There seems to be still some denial in there. I see rust providing today what he calls a fantasy. In fact, it existed before C with languages like ADA, except the ecosystem just wasnt there. Second problem is the timeline. 3 years for a new language version, then 10 years for the ecosystem to upgrade, then another 10 years until everyone is convinced this new way of working should be better? It seems both an aggressive timeline and a promise it wont happen in my professional lifetime. Also, a path forward is not a commitment, e.g. to completely eradicate undefined behavior outside unsafe blocks.
All and all, and I hope I am wrong here, I read this as too little, too late. Rewriting it all from scratch is hard, but erasing the culture of the C++ ecosystem seems a lot harder.
> "maybe crash, maybe accidentally continue running and make things far [worse] than crashing" instead "definitely crash"
…is functionally indistinguishable from your reply.
> (two pointers can reference the same memory and both be valid for reads/writes).
Rather than forbid, Rust requires you put logic like this inside unsafe blocks. This limits the number of places you need to look for UB. Hopefully the number of shared writable pointers is not excessive.
C++ programs on the other hand are all the equivalent of one big unsafe block. That's the difference, not anything "forbidden" by Rust.
https://blog.cloudflare.com/how-we-built-pingora-the-proxy-t...
A non-trivial C++ codebase with that kind of track record is so rare as to be unheard of, though many can approach it with the various sanitizers plugged into the dev workflow after the fact.
C++ has improved dramatically over the last fifteen years, but a lot of stuff simply can't be fixed without breaking backward compatibility, which just isn't going to happen.
We've had enough time elapse to see the related rates of CVEs posted for C++ and Rust apps over the last few years. It's not even close.
It is absolutely possible to have bugs in a Rust app due to logic error or memory leak. But C++ has those same limitations and so many more unless you tack on a host of add-on analysis tools and still you end up with a result that is not as safe as Rust.
Write a web app server in Rust? Sure. As long as I know the problem space, have the dev time allocated, and the need for that efficiency is clear.
Write it in C++? Hell no. Not ever again. Not in a million years. Even if the need for efficiency is demonstrated, I have far less confidence in the integrity of that service when connected to the public internet, no matter how skilled the team is.
Even Scott Meyers—Scott Fucking Meyers, who wrote acclaimed books on advanced use of C++ we mere mortals came to depend upon—does not have confidence in writing code for it anymore. In just three years, he went from an undisputed authority on the topic to this in 2018:
"As you may know, I retired from active involvement in C++ at the end of 2015, and in the ensuing two and a half years, I’ve forgotten enough details of the language that I am no longer able to properly evaluate bug reports regarding the technical aspects of my books. C++ is a large, intricate language with features that interact in complex and subtle ways, and I no longer trust myself to keep all the relevant facts in mind. As a result, all I can do is thank you for your bug report, because I no longer plan to update my books to incorporate technical corrections. Lacking the ability to fairly evaluate whether a bug report is valid, I think this is the only responsible course of action."
https://scottmeyers.blogspot.com/2018/09/the-errata-evaluati...
Neither I nor the folks I have worked with were as skilled as Scott Meyers at his prime, and the majority of us—myself especially—aren't even as good as he was 2.5 years after he stepped away.
Perhaps you are. Are you certain that everyone else on your team is? Everyone who comes later that has to maintain those codebases?
With Rust, I believe teams have a fighting chance. With C++, I'd just as soon buy lotto scratchers since I'm looking at similar odds. Perhaps I'm just an average software engineer. That's entirely possible, and I'll cop to that. But I'm not alone, and we still have bills to pay and code to write. For the sake of my clients, that'll be in Rust before C++ if I can help it. (And neither if the problem doesn't require their level of efficiency.)
A major power outage has nothing to do with reverse proxy software. It's difficult to take your critiques in good faith.
C++ is too complex for an expert to safely identify whether something is a bug or not. Not all C++ developers are experts. It is alarming you consider this state of affairs to be acceptable or that Rust does not clear mitigate many of these issues out of the box.
Does Rust eliminate all bugs? Of course not. That was never the assertion. When Microsoft finds in a study that 70%+ of all Microsoft CVEs would have been avoided given Rust's memory model, it should not be hand-waved away as personal preference or irrational bias. [2] [3]
[1] https://www.cloudflarestatus.com/incidents/hm7491k53ppg
[2] https://msrc.microsoft.com/blog/2019/07/we-need-a-safer-syst...
[3] https://msrc.microsoft.com/blog/2019/07/why-rust-for-safe-sy...
I am glad you recognize how bad of an example that was. Now apply this to the rest of your arguments.
> or that Rust does not clear mitigate many of these issues out of the box.
You're again imputing something I never said only to support your opinion. This is the third time in this thread you're successfully avoiding to address the substance of my initial two comments. I won't proceed any further in this discussion because it's a plain waste of time.
In Rust, it absolutely is. You generally have so few `unsafe` blocks that it's entirely reasonable for a human to audit them and manually verify that their invariants are upheld. You can still use tools like Miri if you want even more assurance, but that's optional.
UB does not happen because there's few lines of code that do the wrong(TM) kind of obvious thing but it happens because that chunk of code interacts with other parts of the code in ways that you usually cannot conceive without tooling or realistic workloads.
I guess that for that or similar reason, Rust also happens to be working on adding support for UBSAN, ASAN, TSAN and MSAN sanitizers. Unfortunately it has been WIP for almost 7 years: https://github.com/rust-lang/rust/issues/39699
I'm sorry for being pedantic, but it's important to distinguish between UB generally (which would normally be termed "implementation-defined" in common parlance if that weren't already a term of art) and memory safety specifically.
We don't get CVEs because a C source file didn't end in a newline. I suspect we rarely get CVEs because someone failed to add -ftrapv when they should have. We get CVEs primarily due to OOB memory access.
This is quite the... unique way of defining "undefined behavior". Rust is currently implementation-defined. That doesn't even remotely mean its behavior is undefined in theory. And it certainly doesn't mean that "all of Rust" is UB in any practical, real-world sense. In practice, your average Rust program is more well-defined than nearly every C codebase, in terms of what invariants the compiler is allowed to assume about the code for the sake of performing transformations (which is what UB actually means, rather than "is there an international standard").
Many cases of UB in C are perfectly well defined at the implementation level. Some are not, for reasons ranging from lack of a demand signal, to the need for an expensive runtime, to compiler writers wanting to squeeze out every last drop of performance.
So while his opinion is highly regarded by some of the ISO WG21 300+ voters, like in politics, if he doesn't manage to win the majority of the voters, and then the compiler writers (which can always ignore part of ISO, and they sometimes do), it hardly matters.
As for the three years, while it may seem a long time, keeping up with six week releases on Rust is also not a panacea, and when Rust eventually gets more than just a reference implementation, like required by law in some industries, it will also slow down.
As example in some of those industries, being able to use certified C++14 or C11 toolchains is already a luxury.
I have to wait a few years for the C++ committee to define profiles. Then a few more years for tooling to become available. Then a few more months for the tooling to become interoperable enough to actually be used in existing build tooling. Then a few more years for all my major dependencies to actually use profiles. Then I can rewrite my code in profiles-C++ -- or by writing safety wrappers around my existing code and all dependencies that do not support the right profiles.
Or I can switch to a memory safe language today. I still have to write safety wrappers around all my code to interface with that, but I'll have a couple of years of a head-start to anybody sticking to C++.
As an example, while Microsoft slowly adopts Rust, it keeps putting out best practices and improved tooling, they aren't going to rewrite the whole Windows, XBox and Azure C++ code into Rust for the next couple of decades, or how long they would still matter on the market place.
Or Apple with they increased adoption of Swift, while still having to deliver C, C++, Objective-C and Objective-C++ stuff.
Or Google slowly adopting Rust, yet it still isn't officially supported on the NDK, or being the main language used on V8.
I just see no way to be able to use current C++ code in a profiles world without wrappers or even a rewrite. For some code with decent semantics, a modern enough code base and clean APIs that wrapper might be just slapping a "compatible with profile FooBar" somewhere. On the other hand those are the APIs that are the easiest to wrap for other languages, too.
> As an example, while Microsoft slowly adopts Rust, it keeps putting out best practices and improved tooling, they aren't going to rewrite the whole Windows, XBox and Azure C++ code into Rust for the next couple of decades, or how long they would still matter on the market place.
So they are making the jump away from C++ now, wrapping their existing code to reuse it from safer languages. Smart :-)
I seriously hope all your competition is in a similar situation or it might become harder and harder for you to meet requirements going forward. The push towards memory-safe languages is out there.
But there's billions (?) of lines of existing C++. For those projects, there are two options: (1) improve compiler static analysis, possibly incrementally update it with something like 'profiles'. (2) Do nothing.
There is no "rewrite it in another language" option. Those are your choices, and even (1) is a stretch.
So I do think we should be moving forward on both fronts - improve C++ so that existing code can be made safer, as well as push the envelope with newer safer languages.
Option 4) The business core is turned into a library. Everything from the command line tools to UI all wrap this in other languages. Everything that is not the core is deleted.
With the C++ committee after the last two decades I am firmly in the I'll believe [shiny feature] when I see it camp.
How about "Wrap your C++ code in FFI wrappers and use it from a safer language"?
It is conceptually not much different to "rewrite all your C++ code to be profile compliant" -- which will involve wrapping existing "unsafe" C++ code you can not just port over to mark it up in such a way that tooling can reason about it better.
> By the time it happens — 40 years from now — we’ll probably have 20 different ones, and they have to interoperate.
C++ doesn't interoperate with anything either due to name mangling being unspecified.
Will attrition make a decades-long timeline viable? I'd never touch C++ myself, I'm too scared there will be a long period of time where I'd be actively dangerous and introduce security holes. I am learning Rust, because that type of low-level systems programming seems like a valuable thing to have.
Are there young devs who aspire to go through the C++ learning curve? I'd love to hear about your experience!
But now the only way forward I see for C++ to maintain its position as a mainstream language is to draw a hard line in the sand and effectively only keep all of the stuff that people refer to when they say "write in Modern C++", and remove everything else.
I don't think it's a very good proposal, personally. For one thing, it effectively amounts to a rewrite of nearly all existing code. For another, the error messages that can be emitted are terrible. Worse, it relies on the compiler to do a lot of heavy lifting that just isn't going to happen in the industries it's needed most for years. It's also opt-in rather than opt-out. Depending on the as-yet(?) unclarified constraints on UB, there may be yet more footguns for those unwise enough to attempt incremental rewrites. Also, because it's C++ there are already a bunch of visual warts like having to continue using gsl::span instead of std::span because of subtly different semantics.
Or you can use a memory safe language and get essentially the same/better guarantees without all the caveats. However, you have to list a different language on future job postings.
Subtly different - by "a line in the sand" I meant that anything past this line is New C++ and anything behind the line is Old C++. Your compiler for New C++ wouldn't compile anything that is Old C++, and the Old C++ compiler wouldn't compiler much of New C++.
Two different languages that both have Current C++ as an ancestor.
> I don't think it's a very good proposal, personally. For one thing, it effectively amounts to a rewrite of nearly all existing code.
For making it a set of errors in the Current C++, yes, it's a bad proposal and not what I proposed. Under my proposal, it's not like your Old C++ compiler will suddenly stop existing, or stop being supported, would it? You'll effectively have decades before this is the case.
> Or you can use a memory safe language and get essentially the same/better guarantees without all the caveats. However, you have to list a different language on future job postings.
Yeah. You list either New C++ or Old C++ (or both, if you can).
Like many others, I gave up on C++ a long time ago and stick with C for those projects that I both 1) do solo, AND, 2) need the low-level access and performance.
Regarding C, it isn't also not standing still and WG14 is quite clearly turning it into "C++ without classes" kind of language, look forward to more _Generic improvements and upcoming lambdas in C29.
That's sorta my point: it worked out excellently for those languages. Those with legacy code and unable to change still use legacy and the new language gets the benefit of remaining relevant.
The point is not "keep that old shit as relevant for as long as possible", the point is "keep the language relevant", and that means jettisoning all the baggage that C++ has.
> Regarding C, it isn't also not standing still and WG14 is quite clearly turning it into "C++ without classes" kind of language, look forward to more _Generic improvements and upcoming lambdas in C29.
It's not standing still, but the pace and volume of additions is simply nowhere near to what the C++ committee does.
As far as C is concerned, while I feel that they are poor stewards of the language, anyway, the future additions do look helpful.
That is not a good idea. Breaking backwards compatibility with a language that large is going to damage the ecosystem. the Python 2 -> 3 transition shows how slow and costly, ironically enough, this can be.
Stroustrup is correct when he says the way forward is evolutionary. In evolution you never cut things, they're always phased out. Vestigial structures stick around. Incremental change is ultimately going to be more successful, causing schisms and splitting the language community is not going to be success.
That hasn't worked in the past for C++. Why would you expect that approach to start working in the future?
I also think that it's a bad idea to have the language's direction set by what the existing (and attritioning) developers want, and not by what it would take to get new devs. A policy like that is almost guaranteed to result in death by attrition.
> Incremental change is ultimately going to be more successful, causing schisms and splitting the language community is not going to be success.
Two things:
1. I think we're defining success differently here. I'm defining it as market-share.[1]
2. You're looking at the way C++ has always done things, which has failed (IMO, anyway) to keep the language mainstream. You're predicting a future where this approach that has failed in the past, will succeed in your predictions.
BTW, I'm not predicting anything; I'm saying that the C++ approach has resulted in a dismal failure for the languages popularity, causing it to lose some ground against every single competitor in that space: Rust, Nim, Zig and more are all eating away at what's left of the C++ developer base after Java and C# took a shark-sized bite from it in the early 00's to late 00's.
All that's left for C++ is gamedev. If we want to avoid that, C++ needs to be more accessible. In order to get to that, it needs to remove anything that can be removed.
[1] Python is an incredible success, having gained marketshare since 3 was released and people started the "slow and costly" migration which only took 10 years for Python 3 to be the most-used language now.
C++, by comparison, has been losing marketshare with each new evolutionary and incremental change that never discards anything.
C++ has been doing what you say is the correct way, and it has been losing its status as a mainstream language with each new standard. Python did it the way you say is incorrect, and is still solid in it's use-case against newer and better languages.
Okay we gotta agree on some baseline reality. C++ is everywhere. Google and Facebook probably work on more active C++ code than there is Rust, Nim and Zig code multiplied by 100 in the entire world. Most machines, web browsers, airplanes, routers, databases, all machine learning libraries, toasters and tanks run on C++. There's about 30x more open C++ jobs than for all other system languages combined.
>C++, by comparison, has been losing marketshare
That's not true either. As flawed as I personally find these indices, C++ has been, quite rapidly , gaining marketshare over the last few years.
https://www.infoworld.com/article/3684848/c-plus-plus-wins-p...
Even if C++ loses everything else, it is still a big chunck of the industry to keep it going for decades to come.
I really hope it can do better than that.
Note that Window ships a kernel driver written in Rust already, Linux (== ChromeOS and Android) are working to add rust support and iOS is moving towards Swift everywhere. Other languages are closing in on all the use cases you mentioned.
I am fully aware of all those efforts, several links have been posted into HN from me, you can find all of them on my submission history.
A language alone, without the ecosystem, certified compilers and plenty of other industry needs isn't enough, it takes time.
Food for thought, despite all the best efforts and almost painless compatibility, after 40 years, there are still industries that would take C over C++ without wasting a single second thinking about it.
But we might be wrong: Some government or consumer org or something _could_ step in and start to require the use of memory safe languages or just discourage the use of C/C++ in anything they buy. That would hasten the replacement of C++. I am afraid this is getting more likely based on how the C++ community handles growing concerns about memory safety outside of the development communities.
I have seen presentation on safety by people I respect for their contributions to the C++ language that all said a combination of these things:
* you said "C/C++", so you must be clueless * you do not know what safety means, let us explain that to you * everybody else does it wrong and is not really secure either * we can not solve the problem, because everybody uses C++ for the tricky bits that other language can not do because they are oh so safe * other languages are not as safe as they claim as they can all call into C++ * it will act swiftly, it will probably only take us a decade or so * you can use some extra tools somehow, that somebody will probably write * asking devs to follow our recommendations has never worked before, so we need something to enforce things. Let's ask all devs to please use this new thing. * Devs unfortunately do not follow best practices and there is nothing we can do about that
That does not seem to be a very convincing communication strategy to me, even less so when other communities show that real improvements are possible.
The current trend of slapping an AI onto everything makes me nervous about our future: why put effort into careful design when it's easier to feed terabytes of data to an AI and hope something good comes out? Nevermind that you now have to sift through tons of garbage it produces.
C++ is deeply flawed to say the least, you won't fix it with AI or anything. It's time to ditch it already.
C++ is just too slow to compile and it's really not nice to use.
C++ is great to write libraries that need to be fast, but in general, most of what people write should be in interpreted languages, and when speed really matters, use C++ to remove bottlenecks.
Most of software doesn't need to be written in C++.
If you wouldn't mind reviewing https://news.ycombinator.com/newsguidelines.html and taking the intended spirit of the site more to heart, we'd be grateful.