I am actually much more pessimistic about Profiles than Simone.
Regardless of the technology the big thing Rust has that C++ does not is safety culture, and that's dominant here. You could also see at the 2024 "Fireside chat" at CppCon that this isn't likely to change any time soon.
The profiles technology isn't very good. But that's insignificant next to the culture problem, once you decided to make the fifteen minute bagpipe dirge your lead single it doesn't really matter whether you use the colored vinyl.
It doesn't show up in the online videos, but there was a huge contingent of people at that fireside chat wanting a reasonable safety story for C++. The committee simply doesn't have representation from those people and don't seem to understand why it's an existential risk to the language community. The delivery timelines are so long here that anything not standardized soon isn't going to arrive for a decade or more. That's all the time in the world for Rust (or even Zig) to break down the remaining barriers.
Yeah because the committee is now people that a) really love C++, and b) don't care enough about safety to use Rust instead.
I think there are plenty of people that must use C++ due to legacy, management or library reasons and they care about safety. But those people aren't going to join language committees.
Sorry man, but I work since 2012 in professional security development in C/C++. Normally no one talks anymore about things like buffer overflows, use after free,... since years. Everyone uses tools to check for this, and in the end it's cheaper than using Rust. The attack vectors we talk about are logic errors and wrong usage of crypto. Things that can happen with Bash, C/C++, Rust and any other language and that you can't check automatically. Additionally to that, we talk about supply chain attacks, a thing that Rust with Cargo falls deep into.
But, based on a initiative of some Rust entusiast of one Team we tried it. Result after a half of a year was to not to use it. Learning a new language is difficult, Rust is for much people not fun to write and a newbie Rust programmer writes worse code than a senior C/C++ programmer, even if it's the same person.
Beside of people hyped by Rust, there is not much interest to replace C/C++. Currently I see no existential risk at all. On the other hand, Rust currently is overhyped, I would not bet that it's easy to find long time experienced Rust developers to maintain your code in a decade.
I came to the same conclusion in a talk I gave to the Munich C++ Meetup [1]. There is a prevalent culture of expecting users to not make mistakes. Library constructs that could be significantly safer-to-use are kept easy-to-use incorrectly, usually with the argument of performance. The irony is that if you look closer, the performance optimization that was done is removing the seatbelts from a small hatchback to safe on weight.
A year or so ago I read that there was a design decision railroaded through the committee about what kind of safety approach could be looked at. Its wording effectively prevented Safe C++. I was not at this meeting so I’m going on what others say:
I’m a big fan of Safe C++ and believe its approach — learning from another language, incremental opt-in (just like all good refactorings, work on code and improve it piece by piece) — would have been the path that solved some genuine problems. Profiles seem a hodgepodge. And — to share personal worries about what I read into what comments like the above imply, this is not a statement — I worry deeply about the relationship between who proposes what, and who has pricklier personalities or less connections, with what approach was accepted.
I wish Safe C++ would continue as a hard fork of the language.
> There is a prevalent culture of expecting users to not make mistakes.
I think the older of us C/C++ programmers come from no-safety languages like assembly language. That doesn't mean that all of us are "macho programmers" (as I was called here once). C's weak typing and compilers emitting warnings give a false sense of security which is tricky to deal with.
The statement you make is not entirely correct. The more correct statement is that there is a prevalent culture of expecting users to find strategies to avoid mistakes. We are engineers. We do what we need with what we have, and we did what we had to with what we had.
When you program with totally unsafe languages, you develop more strategies than just relying on a type checker and borrow checker: RAII, "crash early", TDD, completion-compatible naming conventions, even syntax highlighting (coloring octal numbers differently)...
BUT. the cultural characteristics of the programmers are only one-quarter of the story. The bigger part is about company culture, and more specifically the availability of programmers. You won't promote safer languages and safer practice by convincing programmers that it has zero impact on performance. It's the companies that you need to convince that the safe alternatives are as productive [1] as the less safe alternatives.
> I am actually much more pessimistic about Profiles than Simone.
Likewise. Apparently Stroustrup wrote his first Profiles paper two years before HN existed. That's an incubation period long enough to wonder about its value, for multiple values of "value."
As discussed multiple times, I agree with the sentiment.
I think we are reaching a phase where C++ won't be going away, as it is quite relevant in many fields, however the two languages approach will keep increasing, and many will consider C++26 good enough for such scenarios.
C++26 and not lower, due to reflection.
I am certain anything else beyond C++26 will only be considered by hardcore C++ shops that culturally won't ever use anything else, besides scripting for builds and OS automation tasks.
C and C++ are fundamentally memory-unsafe languages. That doesn't make them bad languages, but it is a reality that you have to face when you work with them. And one of the things we've learned is that building safe abstractions, while not a complete solution, does quite a long way.
And then CISA suggested that "maybe we should stop using memory-unsafe languages." And this has some of the C++ committee utterly terrified; they need something that lets them tell the government that C++, today, is memory-safe. That thing is C++ profiles. It's not about actually making C++ memory-safe, it's about being able to check the box that C++ is memory-safe, and this is so important it needs to be voted into the standards yesterday and why are you guys saying mean things about C++ profiles...
C++ profiles is a magic solution to the problem. As one committee member noted, there's not enough description of profiles yet to even figure out if it can be implemented or not. Instead, it's just a vague, well, compile with -fsanitize=address, compile with fortify-source, use hardened malloc, that makes my code memory-safe, right? And for as long as profiles remains a magic solution to check a box, it will remain vaporware in practice.
One of the real risks I see in the C++ committee is that they seem to want to drive all of the implementers out of the room.
Spot on, since C++11 the committee has increasingly started to design and add features to the standard without any kind of implementation, only after the standard gets ratified, the implementers eventually find out that the design is broken, or has flaws.
A strange phenomenon akin to the Algol 68 days, and no other ISO based language is taking, where standardising existing practice or having a full test implementation is still pretty much what it being done.
How many export templates, GC, type traits defect fixes, volatile behaviour changes, modules, contracts,.... can implementers still put up with?
Regardless of the technology the big thing Rust has that C++ does not is safety culture, and that's dominant here.
True. So many proposals have gone by over the years. Here's one of mine from 2001.[1] Bad idea.
The layers of cruft in C++ have become so deep that it's a career just to understand them.
DARPA has something called the TRACTOR program, "Translate All C to Rust". It's been underway for a year, and they have a consortium of universities working on it. Not much, if anything, has come out.
Disappointing.
Rust is probably too hard. I write 100% safe Rust, and there are times when I hit an ownership structure wall and have to spend several days re-planning. So far I've always succeeded without using "unsafe" or indices, but it drags down productivity.
Although object-oriented programming is out of fashion, classes with inheritance are useful.
It's really hard to do something comparable in Rust. Traits are not that helpful for this.
Go is a good compromise. Safety at a minor cost in performance. Go is good enough for web back end stuff. Go has both GC and "green threads". This automates the problems that wear people down in C++ and Rust.
> So far I've always succeeded without using "unsafe" or indices, but it drags down productivity.
There is a common perception that Rust is less productive than competing languages, but empirical research by Google and others has found this to be wrong. Rust just shifts the effort earlier in the development phase, where the costs are often orders of magnitude lower. You may spend a few hours struggling with the borrow checker, but that saves you countless days of debugging highly non-trivial defects, especially in a larger codebase.
> Although object-oriented programming is out of fashion, classes with inheritance are useful. It's really hard to do something comparable in Rust. Traits are not that helpful for this.
FWIW, "classes with inheritance" in Rust can be very elegantly modeled with generic typestate. (Traits are used as part of this pattern, but are not the full story.) It might look clunky at first glance, but it accurately reflects the underlying semantics.
> So far I've always succeeded without using "unsafe" or indices, but it drags down productivity.
I really don’t understand this perspective. The whole philosophy of Rust is one where you document why “unsafe” is safe. It is not and never has been a goal to make everything safe because that is an impossible goal to merge with high performance systems language because hardware itself is unsafe. It’s why the unsafe keyword exists. If that wasn’t the goal, unsafe wouldn’t.
I dislike Go's minimalism, however it fits something I have been saying for years.
Many languages that predated Java and C#, already had everything that Go offers and then some.
Modula-3, Oberon, Oberon-2, Active Oberon, Component Pascal, Eiffel.
Had Java and C#, just like those, had full support for AOT compilation, value types and the same low level programming capabilities, and many stuff that was still written during 2000-2010 in C or C++ would not have happened, and maybe C++11 would not have been as relevant as it was.
During that decade many people kept writing C or C++, because they lacked mainstream alternatives for AOT compiled languages, and not because they were into low level systems programming.
TRACTOR is currently proceeding. The program is structured in phases. Each phase will present the participants with increasingly difficult challenges to translate. At the end of each phase the participants will be tested and the results of these tests will be publicly announced. The first phase of TRACTOR began in June and will run for six months.
Judging by this https://vt.social/@lina/113056457969145576 rewriting any even remotely complex project to rust will require making decisions (function signatures, ownership and so on) based on information that might not be present in the C code at all, like API conventions. Translator being able to decide on all these things automatically would probably be quite close to solving the halting problem.
I think something less obvious to people is that type inheritance in C++ has several uses outside of building naive object hierarchies. Even if your model is based on composition as is typically the case these days, inheritance is a useful tool for expressing some metaprogramming mechanics and occasionally literal old style inheritance is actually the right thing to do. You don’t need it most of the time but sometimes not having it makes everything much uglier.
As of C++20 in particular, C++ has taken on a very traits-y character if you go all-in on the new language features.
The way out for C++ is probably to lean into compile-time codegen and verification within the language which is already a pretty unique capability. It dramatically reduces the lines of code a developer has to write. Defect rates closely track lines of code written regardless of the language so large improvements in compile-time expressiveness is a pretty big win.
I think there is room for an ML with a modern toolchain story that just omits Rust's borrow checker and does something more boring. Typescript and Rust have primed a large number of developers to be open to it.
Here's the argument for why profiles might work: with all of the profiles enabled, you are only allowed to use the safe subset of C++ and all of the unsafe stuff is hidden behind APIs whose implementations don't have those profiles enabled. Those projects that enable all profiles by default effectively get Swift-like or Rust-like protection.
Like, you could force all array operations to use C++ stdlib primitives, enable full hardening of the stdlib, and then have bounds safety.
And you could force all lifetime operations to use C++ stdlib refcounting primitives, and then have lifetime safety in a Swift-like way (i.e. eager refcounting everywhere).
I can imagine how this falls over but then it might just be a matter of engineering to make it not fall over.
(I'm playing devils advocate a bit since I prefer Fil-C++.)
To address your points:
1. The safe subset of C++ is too small to do anything with.
2. The Standard Library is not written in the safe subset.
My favorite example from the above paper is the problem of std::sort -- the compiler has no idea if both operands are iterators into the same allocation. The function is fundamentally unsafe. Which C++ profile do you turn on to make that safe? Does it ban use of std::sort? Does it ban use of all <algorithms>, all of which work on pointers/iterators that are susceptible to use-after-free UB?
The whole Standard Library is unsafe. I proposed a rigorously safe std2, and that was rejected. And now you propose a safe std2 (using refcounting primitives)--why would that fare better? What does Profiles actually propose? No change in existing code. The compiler simply finds all UB. Right.
Firstly, you need composition. Rust's safety composes. The safe Rust library for farm animals from Geoff, the safe Rust library for cooking recipes by Alice and the safe Rust library for web server by Bert together with my safe program code adds up to my safe Rust farm foods web site.
By having N profiles, where N is intended to be at least five and might grow arbitrarily and be user extensible, C++ guarantees it cannot deliver composition this way.
Maybe they can define some sort of composition and maybe everybody will ship software which conforms to that definition and so eventually they get composition, that's not there today, so it's just a giant unknown at best.
Secondly, of the profiles described so far, most of them are just solving parts of the single overarching problem Rust addresses, for the serial case. So if they ship that, which already involves some amount of new work yet to be finished, you need all of those profiles to get to only partial memory safety.
Which comes to the third part. Once you start down this path, as they found, you realise you actually want a borrowck. You won't call it that of course, because that would be embarrassing. But you'll need to track reference lifetimes and you'll need annotation and you end up building most of the stuff you insisted you didn't want. For now, you can handwave, this is an unsolved static analysis problem. Well, not so much unsolved as you know the solution and you don't like it.
Your idea to do the reference counting everywhere is not something WG21 has looked at, I think the perf cost is sufficiently bad that they won't even glance at it. They're also not going to ship a GC.
Finally though, C++ is a concurrent language. It has a whole memory model which doesn't even make sense if you aren't thinking about concurrency. But to deliver concurrent memory safety without Fil-C's overheads you would want... well, Rust's Send and Sync traits, which sure enough have eerie twins in the Safe C++ proposal. No attempt to solve this is even hinted at in the current profiles proposal, and they would need to work one out and if it's not Send + Sync again they'd need to prove it is correct.
As far as I'm concerned, there are two main issues with profiles:
1. They're either unimplementable or useless (too many false positives and false negatives).
I think this is pretty evident based on the fact that profiles have been proposed for a while and that no real implementation exists. Worse, out of all of the open source projects and for profit companies, noone has been able to implement any sort of static analysis that would even begin to approach the guarantees Rust makes.
2. The language doesn't give you any tools to actually write safe code.
Ok, let's say that someone actually implements safety profiles. And it highlights your usage of a standard library type. What do you do?
Safe C++ didn't require a new standard library just because. The current stdlib is riddled with safety issues that can't really be fixed and would not be fixed because of backwards compatibility.
You're stuck. And so you turn the safety profile off.
> with all of the profiles enabled, you are only allowed to use the safe subset of C++ and all of the unsafe stuff is hidden behind APIs whose implementations don't have those profiles enabled.
This is not the goal of profiles. It’s to be “good enough.” Guaranteed safety isn’t in the cards.
> And you could force all lifetime operations to use C++ stdlib refcounting primitives, and then have lifetime safety in a Swift-like way (i.e. eager refcounting everywhere)
That's going to be a non-starter for 99% of serious C++ projects there. The performance hit is going to be way too large.
For bounds checking, sure I think the performance penalty is so small that it can be done.
There'd be less opposition if profiles worked that way. The real goal is to define a subset that excludes 95% of the unsafe stuff, as opposed to providing hard guarantees.
I would have implemented profiles if profiles had a chance of working. But they will not ever work. I present many examples of why they fail here:
https://www.circle-lang.org/draft-profiles.html
People who say Profiles are a path forward, please address any of the points in this document.
Sean Baxter stated that he is not working on Safe C++ anymore, so that proposal is dead.
But is somebody still working on safety profiles? I have not noticed and profiles related paper seeing updates since Hagenberg. Herb just wrote in his trip report "Profiles papers received a lot of discussion time in EWG (language evolution working group) and feedback to improve consensus,", which leaves any interpretation open.
The title has potential to be a bit misleading, because as the article says, while Sean Baxter's proposal is not being continued, the committee is working on the Profiles proposal, which still will enable some level of safety. So C++ is still working towards safety, just not the Safe C++ safety.
Hardware level safety will arrive first(see Apple support for Memory Integrity Enforcement ), not as fool proof as SafeC++/Rust but no need to change code...
The safety story with Profiles is rather basic (almost laughable honestly) and hardly any improvement over what was already achievable with compiler flags and clang-tidy.
> Profiles seem less radical and more adoptable, a safer-by-default C++ without forcing the Rust model that aims to tackle the most common C++ pitfalls.
They are not rejecting Safe C++; they are rejecting memory safety. Majority of them believes that memory safety is just hype, and minority of them knows it's a problem, but doesn't want to restrict themselves about coding. If code runs, it is fine. If it does not, coder running is fine too.
Does iOS let you run it in another process? That's a common technique to isolate your app from crashy 3rd party components. This can work if you don't pass it untrusted data. If there's untrusted data coming in and you give it to a crashy c++ component, you're just asking to be pwned.
> Our engineers are smart and hardworking but they throw their hands up at this.
Since you don't think this is a skill issue, shouldn't you support Safe C++, which eliminates unsafety rather than just turning a blind eye to it?
> Please tell me my options aren’t limited to “please be better at programming”…?
You can only use Valgrind/ASan, stress testing, and rewriting in other languages to pay off the technical debt. Even if a god points out every bug in your code, you'd still need to put in great effort to fix them. If you don't pay for it while coding, then you must pay for it after coding. There are no shortcuts.
Sorry, but yes, when your app crashes there could be two issues. The C++ library that you use is shit, or your engineers don't understand the underlying concept of allocating/deallocating things because for Swift they had never to learn them. With Rust the code just wouldn't compile at all, that the only difference.
I'm unsure a bout the profiles. If they add restrictions and need to be enabled as a compiler flag, no legacy project I'll use them since they'd probably get like 4 errors and say "oh this options breaks my code, but the code has been running for years so its fine".
Okay, so treat the C++ standards committee the same way the HTML5 people treated W3C. If they insist on making themselves irrelevant, let them.
Profiles cannot achieve the same level of safety as Rust and it's obvious to anyone who breathes. Profiles just delete stuff from the language. Without lifetimes reified as types you can't express semantics with precision enough to check them. The moment string_view appears, you're horked.
Okay, so you ban all uncounted reference types too. Now what you're left with isn't shit Rust but instead shit Swift, one that combines the performance of a turtle with the ergonomics of a porcupine.
There's no value in making things a little bit safer here and there. The purpose of a type system is to embed proofs about invariants. If your system doesn't actually prove the the invariant, you can't rely on it and you've made is a shitty linter.
Continue the safe C++ work outside the context of the C++ standards committee. Its members, if you ignore their words and focus on the behaviors, would rather see the language become irrelevant than change decades old practices. Typical iron law of bureaucracy territory.
The reason why WHATWG was able to take over HTML like that is because all the people & companies that were actually making the browsers were onboard.
With C++, my impression is that most implementers simply aren't interested. And, conversely, most people who might be interested enough to roll a new implementation have already moved to Rust and make better use of their time improving that.
The browser companies weren't just onboard with WHATWG – they literally are WHATWG. The WHATWG steering committee is Apple, Google, Microsoft, and Mozilla.
You're right, but dammit, I wish you weren't. A world in which we can evolve existing large C++ codebases gradually towards safety instead of having to RRiR is a better world.
There are lots of cool innovations C++ made that will just disappear from the Earth, forever, if C++ can't be made memory safe in the same sense Rust is. I mean, Rust doesn't even support template specialization.
I don't think it's too late for someone to fork both C++ and Clang and make something that's actually a good synthesis of the old and the new.
But yeah, the most likely future is one on which C++ goes the way of Fortran (which still gets regular updates, however irrelevant) and the energy goes into Rust. But I like to rage, rage, against the dying of the type based metaprogramming.
> Profiles cannot achieve the same level of safety as Rust
So the claim is that the scpptool approach[1] can, while remaining closer to traditional C++, and not requiring the introduction of new language elements. Since the scpptool-enforced safe subset of C++ is an actual subset of C++, conforming code continues to build with your existing compiler. It just uses an additional static analyzer to check conformance.
For the 90% or whatever of C++ code that is not actually performance sensitive, the associated SaferCPlusPlus library provides drop-in and "one-to-one" safe replacements for unsafe C++ elements (like standard library containers and raw pointers). (For example, if you're worried about potentially invalid vector iterators, you can just replace your std::vector<>s with mse::mstd::vector<>s.) With these elements, most of the safety is enforced in the type system and not reliant on the static analyzer.
Conforming implementations of performance-sensitive code would be more restricted and more reliant on the static analyzer for safety enforcement. And sometimes requires the use of library elements, like "borrowing objects", which may not have analogies in traditional C++. But overall, even high-performance conforming code remains very recognizable C++.
The claim is that the scpptool approach is a straightforward path to full memory (and data race) safety for C++, and the one that requires the least code migration effort. (And again, as an actual subset of existing C++, not technically dependent on standard committees or compiler vendors for its implementation or deployment.)
Call me stupid for asking, but what is "safe" here? I get the length-checked buffer copies and accesses, is there anything else? Less allowed type conversions?
There is an old definition of language safety which means "no untrapped execution errors". It is not the only way to define safety, but it is a good way that you can adapt to various kinds of x-safety, such as memory safety.
You are talking about spatial safety. There are a few other types of memory safety:
- temporal safety (e.g. no use after free)
- initialization safety (no read of initialized memory)
- thread safety (no data races)
- type safety (accessing memory with the correct type)
I'm not up to date with the latest developments in C++ but would't it be straightforward to do something like "#pragma pointer_safety strong" which would force the compiler to only accept the use of smart pointers or something along those lines. Was anything like this proposed so far?
You might be interested in this talk[0] by a WebKit engineer on how they're implementing similar approaches using libTooling and their own smart pointer types.
For example, their tooling prevents code like this:
if (m_weakMember) { m_weakMember->doThing(); }
from compiling, forcing you to explicitly create an owning local reference, like so:
if (RefPtr strongLocal = m_weakMember.get()) { strongLocal->doThing(); }
unless it's a trivial inlined function, like a simple getter.
My interpretation of Geoff's presentation is that some version of profiles might work, at least in the sense of making it possible to write C++ code that is substantially safer than what we have today.
I don't think that really accomplishes anything. If you interpret it broadly enough to meaningfully improve safety you have to ban so much stuff that no codebase will ever turn it on. It's a pretty straightforward locally-verifiable property as well, so people who really want it don't need a pragma to enforce it.
The problem with this would probably be that you usually have to use some libraries with C APIs and regular pointers.
You could compile your program with address sanitizer then it at least crashes in a defined way at runtime when memory corruption would happen. TCC (tiny C compiler initially written by fabrice bellard) also has such a feature I think.
That's what the "Profiles" feature is. The problem is that any nontrivial real world program in a non-GC language needs non-owning reference types to perform well, and you can't express the rules for safe use of non-owning references without augmenting the language. People have tried. You need something more sophisticated than using smart pointers for everything. In the limit, smart pointers for everything is just called "Python".
What infuriates me about the C++ safety situation is that C++ is by and large a better, more expressive language than Rust is, particularly with respect to compile time type level metaprogramming. And I am being walked hands handcuffed behind my back, alongside everyone else, into the Rust world with its comparatively anemic proc macro shit because the C++ committee can't be bothered to care about memory safety.
Because of the C++ standards committee's misfeasance, I'm going to have to live in a world where I don't get to use some of my favorite programming techniques.
> You need something more sophisticated than using smart pointers for everything. In the limit, smart pointers for everything is just called "Python".
I don't see how that follows at all. What makes Python Python (and slow!) is dynamic dispatch everywhere down to the most primitive things. Refcounted smart pointers are a very minor thing in the big picture, which is why we've seen Python implementations without them (Jython, IronPython). Performance-wise, yes, refcounting certainly isn't cheap, but you just do that and keep everything else C++-like, the overall performance profile of such a language is still much closer to C++ than to something like Python.
You can also have refcounting + something like `ref` types in modern C# (which are essentially restricted-lifetime zero-overhead pointers with inferred or very simplistic lifetimes):
It doesn't cover all the cases that a full-fledged borrow checked with explicit lifetime annotations can, but it does cover quite a few; perhaps enough to adopt the position that refcounting is "good enough" for the rest.
> In the limit, smart pointers for everything is just called "Python".
To be more precise, it's old Python. Recent versions of Python use a gc.
> And I am being walked hands handcuffed behind my back, alongside everyone else, into the Rust world with its comparatively anemic proc macro shit because the C++ committee can't be bothered to care about memory safety.
Out of curiosity (as someone working on static analysis), what properties would you like your compiler to check?
I do want C++ to be a safer language, but I don't think inheriting the Rust safety model is the way to go. It is in a way revolutionary but has major downsides like inability to deal with cyclic data structures without clumpsy workarounds.
I don't want to play with a plastic sword, just put it in a sheath.
The mentioned proposal isn't really that great. It basically tries to make C++ to Rust by blindly copying many its ideas. Many of them aren't strictly necessary to achieve safety in C++. There are different proposals for safety, which are way smaller and simpler than this one.
Porting Rust enums and pattern matching isn't necessary (C++ already has std::variant).
Lifetime parameters aren't necessary, lifetime contracts may be implemented in a different and much easier way. This may be expressed in form of a function attribute, which may be calculated via constexpr code.
Special operators for borrowing just add more complexity. C++ already achieves same behavior by normal references (which may be mutable and non-mutable).
Introducing immutability by default isn't strictly necessary for achieving safety. C++ developers are already mostly fine writing "const" almost everywhere.
C++ will never be safe as long as its C root persists, it doesn't matters how much freatures you add on top of C++ to make writing safe programs more convenient.
You need to take off the "inherently unsafe" C root from C++, but it wouldn't be called C++ anymore by that point.
I am actually much more pessimistic about Profiles than Simone.
Regardless of the technology the big thing Rust has that C++ does not is safety culture, and that's dominant here. You could also see at the 2024 "Fireside chat" at CppCon that this isn't likely to change any time soon.
The profiles technology isn't very good. But that's insignificant next to the culture problem, once you decided to make the fifteen minute bagpipe dirge your lead single it doesn't really matter whether you use the colored vinyl.
It doesn't show up in the online videos, but there was a huge contingent of people at that fireside chat wanting a reasonable safety story for C++. The committee simply doesn't have representation from those people and don't seem to understand why it's an existential risk to the language community. The delivery timelines are so long here that anything not standardized soon isn't going to arrive for a decade or more. That's all the time in the world for Rust (or even Zig) to break down the remaining barriers.
Profiles and sanitizers just aren't sufficient.
Yeah because the committee is now people that a) really love C++, and b) don't care enough about safety to use Rust instead.
I think there are plenty of people that must use C++ due to legacy, management or library reasons and they care about safety. But those people aren't going to join language committees.
32 replies →
Sorry man, but I work since 2012 in professional security development in C/C++. Normally no one talks anymore about things like buffer overflows, use after free,... since years. Everyone uses tools to check for this, and in the end it's cheaper than using Rust. The attack vectors we talk about are logic errors and wrong usage of crypto. Things that can happen with Bash, C/C++, Rust and any other language and that you can't check automatically. Additionally to that, we talk about supply chain attacks, a thing that Rust with Cargo falls deep into.
But, based on a initiative of some Rust entusiast of one Team we tried it. Result after a half of a year was to not to use it. Learning a new language is difficult, Rust is for much people not fun to write and a newbie Rust programmer writes worse code than a senior C/C++ programmer, even if it's the same person.
Beside of people hyped by Rust, there is not much interest to replace C/C++. Currently I see no existential risk at all. On the other hand, Rust currently is overhyped, I would not bet that it's easy to find long time experienced Rust developers to maintain your code in a decade.
2 replies →
I came to the same conclusion in a talk I gave to the Munich C++ Meetup [1]. There is a prevalent culture of expecting users to not make mistakes. Library constructs that could be significantly safer-to-use are kept easy-to-use incorrectly, usually with the argument of performance. The irony is that if you look closer, the performance optimization that was done is removing the seatbelts from a small hatchback to safe on weight.
[1] https://youtu.be/rZ7QQWKP8Rk or text form https://github.com/Voultapher/Presentations/blob/main/safety...
A year or so ago I read that there was a design decision railroaded through the committee about what kind of safety approach could be looked at. Its wording effectively prevented Safe C++. I was not at this meeting so I’m going on what others say:
https://www.reddit.com/r/cpp/comments/1hppdzc/comment/m4jjo4...
I’m a big fan of Safe C++ and believe its approach — learning from another language, incremental opt-in (just like all good refactorings, work on code and improve it piece by piece) — would have been the path that solved some genuine problems. Profiles seem a hodgepodge. And — to share personal worries about what I read into what comments like the above imply, this is not a statement — I worry deeply about the relationship between who proposes what, and who has pricklier personalities or less connections, with what approach was accepted.
I wish Safe C++ would continue as a hard fork of the language.
2 replies →
> There is a prevalent culture of expecting users to not make mistakes.
I think the older of us C/C++ programmers come from no-safety languages like assembly language. That doesn't mean that all of us are "macho programmers" (as I was called here once). C's weak typing and compilers emitting warnings give a false sense of security which is tricky to deal with.
The statement you make is not entirely correct. The more correct statement is that there is a prevalent culture of expecting users to find strategies to avoid mistakes. We are engineers. We do what we need with what we have, and we did what we had to with what we had.
When you program with totally unsafe languages, you develop more strategies than just relying on a type checker and borrow checker: RAII, "crash early", TDD, completion-compatible naming conventions, even syntax highlighting (coloring octal numbers differently)...
BUT. the cultural characteristics of the programmers are only one-quarter of the story. The bigger part is about company culture, and more specifically the availability of programmers. You won't promote safer languages and safer practice by convincing programmers that it has zero impact on performance. It's the companies that you need to convince that the safe alternatives are as productive [1] as the less safe alternatives.
[1] https://xkcd.com/303/
4 replies →
> I am actually much more pessimistic about Profiles than Simone.
Likewise. Apparently Stroustrup wrote his first Profiles paper two years before HN existed. That's an incubation period long enough to wonder about its value, for multiple values of "value."
As discussed multiple times, I agree with the sentiment.
I think we are reaching a phase where C++ won't be going away, as it is quite relevant in many fields, however the two languages approach will keep increasing, and many will consider C++26 good enough for such scenarios.
C++26 and not lower, due to reflection.
I am certain anything else beyond C++26 will only be considered by hardcore C++ shops that culturally won't ever use anything else, besides scripting for builds and OS automation tasks.
C and C++ are fundamentally memory-unsafe languages. That doesn't make them bad languages, but it is a reality that you have to face when you work with them. And one of the things we've learned is that building safe abstractions, while not a complete solution, does quite a long way.
And then CISA suggested that "maybe we should stop using memory-unsafe languages." And this has some of the C++ committee utterly terrified; they need something that lets them tell the government that C++, today, is memory-safe. That thing is C++ profiles. It's not about actually making C++ memory-safe, it's about being able to check the box that C++ is memory-safe, and this is so important it needs to be voted into the standards yesterday and why are you guys saying mean things about C++ profiles...
C++ profiles is a magic solution to the problem. As one committee member noted, there's not enough description of profiles yet to even figure out if it can be implemented or not. Instead, it's just a vague, well, compile with -fsanitize=address, compile with fortify-source, use hardened malloc, that makes my code memory-safe, right? And for as long as profiles remains a magic solution to check a box, it will remain vaporware in practice.
One of the real risks I see in the C++ committee is that they seem to want to drive all of the implementers out of the room.
Spot on, since C++11 the committee has increasingly started to design and add features to the standard without any kind of implementation, only after the standard gets ratified, the implementers eventually find out that the design is broken, or has flaws.
A strange phenomenon akin to the Algol 68 days, and no other ISO based language is taking, where standardising existing practice or having a full test implementation is still pretty much what it being done.
How many export templates, GC, type traits defect fixes, volatile behaviour changes, modules, contracts,.... can implementers still put up with?
2 replies →
Regardless of the technology the big thing Rust has that C++ does not is safety culture, and that's dominant here.
True. So many proposals have gone by over the years. Here's one of mine from 2001.[1] Bad idea. The layers of cruft in C++ have become so deep that it's a career just to understand them.
DARPA has something called the TRACTOR program, "Translate All C to Rust". It's been underway for a year, and they have a consortium of universities working on it. Not much, if anything, has come out. Disappointing.
Rust is probably too hard. I write 100% safe Rust, and there are times when I hit an ownership structure wall and have to spend several days re-planning. So far I've always succeeded without using "unsafe" or indices, but it drags down productivity.
Although object-oriented programming is out of fashion, classes with inheritance are useful. It's really hard to do something comparable in Rust. Traits are not that helpful for this.
Go is a good compromise. Safety at a minor cost in performance. Go is good enough for web back end stuff. Go has both GC and "green threads". This automates the problems that wear people down in C++ and Rust.
[1] https://www.animats.com/papers/languages/cppstrictpointers.h...
> So far I've always succeeded without using "unsafe" or indices, but it drags down productivity.
There is a common perception that Rust is less productive than competing languages, but empirical research by Google and others has found this to be wrong. Rust just shifts the effort earlier in the development phase, where the costs are often orders of magnitude lower. You may spend a few hours struggling with the borrow checker, but that saves you countless days of debugging highly non-trivial defects, especially in a larger codebase.
> Although object-oriented programming is out of fashion, classes with inheritance are useful. It's really hard to do something comparable in Rust. Traits are not that helpful for this.
FWIW, "classes with inheritance" in Rust can be very elegantly modeled with generic typestate. (Traits are used as part of this pattern, but are not the full story.) It might look clunky at first glance, but it accurately reflects the underlying semantics.
7 replies →
> So far I've always succeeded without using "unsafe" or indices, but it drags down productivity.
I really don’t understand this perspective. The whole philosophy of Rust is one where you document why “unsafe” is safe. It is not and never has been a goal to make everything safe because that is an impossible goal to merge with high performance systems language because hardware itself is unsafe. It’s why the unsafe keyword exists. If that wasn’t the goal, unsafe wouldn’t.
5 replies →
I dislike Go's minimalism, however it fits something I have been saying for years.
Many languages that predated Java and C#, already had everything that Go offers and then some.
Modula-3, Oberon, Oberon-2, Active Oberon, Component Pascal, Eiffel.
Had Java and C#, just like those, had full support for AOT compilation, value types and the same low level programming capabilities, and many stuff that was still written during 2000-2010 in C or C++ would not have happened, and maybe C++11 would not have been as relevant as it was.
During that decade many people kept writing C or C++, because they lacked mainstream alternatives for AOT compiled languages, and not because they were into low level systems programming.
> The layers of cruft in C++ have become so deep that it's a career just to understand them.
The committee have, over decades, dug themselves into a hole that they won’t be able to get out of, even if they wanted to.
C++ does have some features that I appreciate, but for every new project I begin it has to contend with Rust and OCaml, and most of the time it loses.
It will stay relevant for existing projects, but becoming the language of choice for new projects will only get harder with time.
> Go is a good compromise
Go doesn't prevent data races.. besides the borrow checker, the thing that makes Rust special is the Send and Sync traits
TRACTOR is currently proceeding. The program is structured in phases. Each phase will present the participants with increasingly difficult challenges to translate. At the end of each phase the participants will be tested and the results of these tests will be publicly announced. The first phase of TRACTOR began in June and will run for six months.
Judging by this https://vt.social/@lina/113056457969145576 rewriting any even remotely complex project to rust will require making decisions (function signatures, ownership and so on) based on information that might not be present in the C code at all, like API conventions. Translator being able to decide on all these things automatically would probably be quite close to solving the halting problem.
1 reply →
> Go is a good compromise. Safety at a minor cost in performance. Go is good enough for web back end stuff. Go has both GC and "green threads".
Or, for even better performance, you can use Java (24+), which has both "green threads" and a more advanced and performant GC and compiler than Go.
I think something less obvious to people is that type inheritance in C++ has several uses outside of building naive object hierarchies. Even if your model is based on composition as is typically the case these days, inheritance is a useful tool for expressing some metaprogramming mechanics and occasionally literal old style inheritance is actually the right thing to do. You don’t need it most of the time but sometimes not having it makes everything much uglier.
As of C++20 in particular, C++ has taken on a very traits-y character if you go all-in on the new language features.
The way out for C++ is probably to lean into compile-time codegen and verification within the language which is already a pretty unique capability. It dramatically reduces the lines of code a developer has to write. Defect rates closely track lines of code written regardless of the language so large improvements in compile-time expressiveness is a pretty big win.
1 reply →
I think there is room for an ML with a modern toolchain story that just omits Rust's borrow checker and does something more boring. Typescript and Rust have primed a large number of developers to be open to it.
4 replies →
And I would say the deficiencies in Profiles and the fact Safe C++ was killed is the technical decisions reflecting the culture problem.
The first four letters of "culture" are certainly right.
> The profiles technology isn't very good.
Can you be very specific about why?
Here's the argument for why profiles might work: with all of the profiles enabled, you are only allowed to use the safe subset of C++ and all of the unsafe stuff is hidden behind APIs whose implementations don't have those profiles enabled. Those projects that enable all profiles by default effectively get Swift-like or Rust-like protection.
Like, you could force all array operations to use C++ stdlib primitives, enable full hardening of the stdlib, and then have bounds safety.
And you could force all lifetime operations to use C++ stdlib refcounting primitives, and then have lifetime safety in a Swift-like way (i.e. eager refcounting everywhere).
I can imagine how this falls over but then it might just be a matter of engineering to make it not fall over.
(I'm playing devils advocate a bit since I prefer Fil-C++.)
I illustrate why it won't work with a number of examples here: https://www.circle-lang.org/draft-profiles.html
To address your points: 1. The safe subset of C++ is too small to do anything with. 2. The Standard Library is not written in the safe subset.
My favorite example from the above paper is the problem of std::sort -- the compiler has no idea if both operands are iterators into the same allocation. The function is fundamentally unsafe. Which C++ profile do you turn on to make that safe? Does it ban use of std::sort? Does it ban use of all <algorithms>, all of which work on pointers/iterators that are susceptible to use-after-free UB?
The whole Standard Library is unsafe. I proposed a rigorously safe std2, and that was rejected. And now you propose a safe std2 (using refcounting primitives)--why would that fare better? What does Profiles actually propose? No change in existing code. The compiler simply finds all UB. Right.
If that is what profiles were actually doing, it would probably make sense. But it's not what profiles are doing.
Instead, for example, the lifetime safety profile (https://github.com/isocpp/CppCoreGuidelines/blob/master/docs...) is a Rust-like compile time borrow checker that relies on annotations like [[clang::lifetimebound]], yet they also repeatedly insist that profiles will not require this kind of annotation (see the papers linked from https://www.circle-lang.org/draft-profiles.html#abstract).
Their messaging is just not consistent with the concrete proposals they have described, let alone actually implemented.
1 reply →
Yes I can be specific.
Firstly, you need composition. Rust's safety composes. The safe Rust library for farm animals from Geoff, the safe Rust library for cooking recipes by Alice and the safe Rust library for web server by Bert together with my safe program code adds up to my safe Rust farm foods web site.
By having N profiles, where N is intended to be at least five and might grow arbitrarily and be user extensible, C++ guarantees it cannot deliver composition this way.
Maybe they can define some sort of composition and maybe everybody will ship software which conforms to that definition and so eventually they get composition, that's not there today, so it's just a giant unknown at best.
Secondly, of the profiles described so far, most of them are just solving parts of the single overarching problem Rust addresses, for the serial case. So if they ship that, which already involves some amount of new work yet to be finished, you need all of those profiles to get to only partial memory safety.
Which comes to the third part. Once you start down this path, as they found, you realise you actually want a borrowck. You won't call it that of course, because that would be embarrassing. But you'll need to track reference lifetimes and you'll need annotation and you end up building most of the stuff you insisted you didn't want. For now, you can handwave, this is an unsolved static analysis problem. Well, not so much unsolved as you know the solution and you don't like it.
Your idea to do the reference counting everywhere is not something WG21 has looked at, I think the perf cost is sufficiently bad that they won't even glance at it. They're also not going to ship a GC.
Finally though, C++ is a concurrent language. It has a whole memory model which doesn't even make sense if you aren't thinking about concurrency. But to deliver concurrent memory safety without Fil-C's overheads you would want... well, Rust's Send and Sync traits, which sure enough have eerie twins in the Safe C++ proposal. No attempt to solve this is even hinted at in the current profiles proposal, and they would need to work one out and if it's not Send + Sync again they'd need to prove it is correct.
4 replies →
As far as I'm concerned, there are two main issues with profiles:
1. They're either unimplementable or useless (too many false positives and false negatives).
I think this is pretty evident based on the fact that profiles have been proposed for a while and that no real implementation exists. Worse, out of all of the open source projects and for profit companies, noone has been able to implement any sort of static analysis that would even begin to approach the guarantees Rust makes.
2. The language doesn't give you any tools to actually write safe code.
Ok, let's say that someone actually implements safety profiles. And it highlights your usage of a standard library type. What do you do?
Safe C++ didn't require a new standard library just because. The current stdlib is riddled with safety issues that can't really be fixed and would not be fixed because of backwards compatibility.
You're stuck. And so you turn the safety profile off.
> with all of the profiles enabled, you are only allowed to use the safe subset of C++ and all of the unsafe stuff is hidden behind APIs whose implementations don't have those profiles enabled.
This is not the goal of profiles. It’s to be “good enough.” Guaranteed safety isn’t in the cards.
7 replies →
My limited understanding is. There is no safe subset (That's what was just discontinued, profiles are the alternative.)
And C++ code simply doesn't have the necessary info to make safety decisions. Sean explains it better than I can https://www.circle-lang.org/draft-profiles.html
7 replies →
> And you could force all lifetime operations to use C++ stdlib refcounting primitives, and then have lifetime safety in a Swift-like way (i.e. eager refcounting everywhere)
That's going to be a non-starter for 99% of serious C++ projects there. The performance hit is going to be way too large.
For bounds checking, sure I think the performance penalty is so small that it can be done.
5 replies →
There'd be less opposition if profiles worked that way. The real goal is to define a subset that excludes 95% of the unsafe stuff, as opposed to providing hard guarantees.
[dead]
I would have implemented profiles if profiles had a chance of working. But they will not ever work. I present many examples of why they fail here: https://www.circle-lang.org/draft-profiles.html
People who say Profiles are a path forward, please address any of the points in this document.
Sean Baxter stated that he is not working on Safe C++ anymore, so that proposal is dead.
But is somebody still working on safety profiles? I have not noticed and profiles related paper seeing updates since Hagenberg. Herb just wrote in his trip report "Profiles papers received a lot of discussion time in EWG (language evolution working group) and feedback to improve consensus,", which leaves any interpretation open.
"If you want to write like Rust, just write Rust". Exactly. No reason not to. RIP cpp
> "If you want to write like Rust, just write Rust".
And if you want to write like D...
The title has potential to be a bit misleading, because as the article says, while Sean Baxter's proposal is not being continued, the committee is working on the Profiles proposal, which still will enable some level of safety. So C++ is still working towards safety, just not the Safe C++ safety.
Seems clear enough to me. The "Safe C++" proposal is not being continued. Profiles is not what was proposed in "Safe C++."
The quotes you have added are not in the title, and they would of course make it less ambiguous.
Hardware level safety will arrive first(see Apple support for Memory Integrity Enforcement ), not as fool proof as SafeC++/Rust but no need to change code...
It has been already here since 2015 on Solaris SPARC.
C++ is working towards safety with the same enthusiasm with which I tackle AI-generated merge requests.
The safety story with Profiles is rather basic (almost laughable honestly) and hardly any improvement over what was already achievable with compiler flags and clang-tidy.
From the article:
> Profiles seem less radical and more adoptable, a safer-by-default C++ without forcing the Rust model that aims to tackle the most common C++ pitfalls.
They are not rejecting Safe C++; they are rejecting memory safety. Majority of them believes that memory safety is just hype, and minority of them knows it's a problem, but doesn't want to restrict themselves about coding. If code runs, it is fine. If it does not, coder running is fine too.
The principles document that was accepted feels very targeted at Safe C++ specifically. It’s fair to say they rejected it.
I work on a Swift/iOS app that wraps a C++ library
90+% of our crashes are from hard-to-diagnose cpp crashes. Our engineers are smart and hardworking but they throw their hands up at this.
Please tell me my options aren’t limited to “please be better at programming”…?
Does iOS let you run it in another process? That's a common technique to isolate your app from crashy 3rd party components. This can work if you don't pass it untrusted data. If there's untrusted data coming in and you give it to a crashy c++ component, you're just asking to be pwned.
For containing legacy C++ codebases https://news.ycombinator.com/item?id=45133938 .. but currently doesn't support iOS.
> Our engineers are smart and hardworking but they throw their hands up at this.
Since you don't think this is a skill issue, shouldn't you support Safe C++, which eliminates unsafety rather than just turning a blind eye to it?
> Please tell me my options aren’t limited to “please be better at programming”…?
You can only use Valgrind/ASan, stress testing, and rewriting in other languages to pay off the technical debt. Even if a god points out every bug in your code, you'd still need to put in great effort to fix them. If you don't pay for it while coding, then you must pay for it after coding. There are no shortcuts.
Have you tried enabling asan? It’s not really the same kind of language guarantees but it does catch a lot of the same errors.
In general I think static analysis is a crutch for C++ to claim safety but it is still a very useful tool that devs should use in development.
Sorry, but yes, when your app crashes there could be two issues. The C++ library that you use is shit, or your engineers don't understand the underlying concept of allocating/deallocating things because for Swift they had never to learn them. With Rust the code just wouldn't compile at all, that the only difference.
I'm unsure a bout the profiles. If they add restrictions and need to be enabled as a compiler flag, no legacy project I'll use them since they'd probably get like 4 errors and say "oh this options breaks my code, but the code has been running for years so its fine".
Neither will those projects use Safe C++
Okay, so treat the C++ standards committee the same way the HTML5 people treated W3C. If they insist on making themselves irrelevant, let them.
Profiles cannot achieve the same level of safety as Rust and it's obvious to anyone who breathes. Profiles just delete stuff from the language. Without lifetimes reified as types you can't express semantics with precision enough to check them. The moment string_view appears, you're horked.
Okay, so you ban all uncounted reference types too. Now what you're left with isn't shit Rust but instead shit Swift, one that combines the performance of a turtle with the ergonomics of a porcupine.
There's no value in making things a little bit safer here and there. The purpose of a type system is to embed proofs about invariants. If your system doesn't actually prove the the invariant, you can't rely on it and you've made is a shitty linter.
Continue the safe C++ work outside the context of the C++ standards committee. Its members, if you ignore their words and focus on the behaviors, would rather see the language become irrelevant than change decades old practices. Typical iron law of bureaucracy territory.
The reason why WHATWG was able to take over HTML like that is because all the people & companies that were actually making the browsers were onboard.
With C++, my impression is that most implementers simply aren't interested. And, conversely, most people who might be interested enough to roll a new implementation have already moved to Rust and make better use of their time improving that.
The browser companies weren't just onboard with WHATWG – they literally are WHATWG. The WHATWG steering committee is Apple, Google, Microsoft, and Mozilla.
You right, because the main companies with OSes that contribute to the surviving compilers that still care about ISO, are now focused elsewhere.
Apple with Swift, Google with Go, Java/Kotlin, Rust, Microsoft with C#, Go, Java and Rust.
Most modules stuff on GCC was done by a single developer, if I am not mistaken.
Notice how Visual C++ blog posts are mostly about game development related improvements, Visual Studio tooling.
Everyone else their compilers are still stuck on C++14, or C++17 if lucky.
You're right, but dammit, I wish you weren't. A world in which we can evolve existing large C++ codebases gradually towards safety instead of having to RRiR is a better world.
There are lots of cool innovations C++ made that will just disappear from the Earth, forever, if C++ can't be made memory safe in the same sense Rust is. I mean, Rust doesn't even support template specialization.
I don't think it's too late for someone to fork both C++ and Clang and make something that's actually a good synthesis of the old and the new.
But yeah, the most likely future is one on which C++ goes the way of Fortran (which still gets regular updates, however irrelevant) and the energy goes into Rust. But I like to rage, rage, against the dying of the type based metaprogramming.
14 replies →
> Profiles cannot achieve the same level of safety as Rust
So the claim is that the scpptool approach[1] can, while remaining closer to traditional C++, and not requiring the introduction of new language elements. Since the scpptool-enforced safe subset of C++ is an actual subset of C++, conforming code continues to build with your existing compiler. It just uses an additional static analyzer to check conformance.
For the 90% or whatever of C++ code that is not actually performance sensitive, the associated SaferCPlusPlus library provides drop-in and "one-to-one" safe replacements for unsafe C++ elements (like standard library containers and raw pointers). (For example, if you're worried about potentially invalid vector iterators, you can just replace your std::vector<>s with mse::mstd::vector<>s.) With these elements, most of the safety is enforced in the type system and not reliant on the static analyzer.
Conforming implementations of performance-sensitive code would be more restricted and more reliant on the static analyzer for safety enforcement. And sometimes requires the use of library elements, like "borrowing objects", which may not have analogies in traditional C++. But overall, even high-performance conforming code remains very recognizable C++.
The claim is that the scpptool approach is a straightforward path to full memory (and data race) safety for C++, and the one that requires the least code migration effort. (And again, as an actual subset of existing C++, not technically dependent on standard committees or compiler vendors for its implementation or deployment.)
[1]: https://github.com/duneroadrunner/scpptool/blob/master/appro...
I don’t think anyone is surprised.
Call me stupid for asking, but what is "safe" here? I get the length-checked buffer copies and accesses, is there anything else? Less allowed type conversions?
There is an old definition of language safety which means "no untrapped execution errors". It is not the only way to define safety, but it is a good way that you can adapt to various kinds of x-safety, such as memory safety.
I have a little post that explains this using a few more words, if interested: https://burakemir.ch/post/memory-safety-the-missing-def/
You are talking about spatial safety. There are a few other types of memory safety:
- temporal safety (e.g. no use after free) - initialization safety (no read of initialized memory) - thread safety (no data races) - type safety (accessing memory with the correct type)
I'm not up to date with the latest developments in C++ but would't it be straightforward to do something like "#pragma pointer_safety strong" which would force the compiler to only accept the use of smart pointers or something along those lines. Was anything like this proposed so far?
You might be interested in this talk[0] by a WebKit engineer on how they're implementing similar approaches using libTooling and their own smart pointer types.
For example, their tooling prevents code like this:
from compiling, forcing you to explicitly create an owning local reference, like so:
unless it's a trivial inlined function, like a simple getter.
[0]https://www.youtube.com/watch?v=RLw13wLM5Ko
I was going to link to this.
My interpretation of Geoff's presentation is that some version of profiles might work, at least in the sense of making it possible to write C++ code that is substantially safer than what we have today.
4 replies →
I don't think that really accomplishes anything. If you interpret it broadly enough to meaningfully improve safety you have to ban so much stuff that no codebase will ever turn it on. It's a pretty straightforward locally-verifiable property as well, so people who really want it don't need a pragma to enforce it.
The problem with this would probably be that you usually have to use some libraries with C APIs and regular pointers.
You could compile your program with address sanitizer then it at least crashes in a defined way at runtime when memory corruption would happen. TCC (tiny C compiler initially written by fabrice bellard) also has such a feature I think.
This of course makes it significantly slower.
> pragma pointer_safety strong" which would force the compiler to only accept the use of smart pointers
You’d possibly just be trading one problem for another though - ask anyone who’s had to debug a shared ownership issue.
That's what the "Profiles" feature is. The problem is that any nontrivial real world program in a non-GC language needs non-owning reference types to perform well, and you can't express the rules for safe use of non-owning references without augmenting the language. People have tried. You need something more sophisticated than using smart pointers for everything. In the limit, smart pointers for everything is just called "Python".
What infuriates me about the C++ safety situation is that C++ is by and large a better, more expressive language than Rust is, particularly with respect to compile time type level metaprogramming. And I am being walked hands handcuffed behind my back, alongside everyone else, into the Rust world with its comparatively anemic proc macro shit because the C++ committee can't be bothered to care about memory safety.
Because of the C++ standards committee's misfeasance, I'm going to have to live in a world where I don't get to use some of my favorite programming techniques.
> You need something more sophisticated than using smart pointers for everything. In the limit, smart pointers for everything is just called "Python".
I don't see how that follows at all. What makes Python Python (and slow!) is dynamic dispatch everywhere down to the most primitive things. Refcounted smart pointers are a very minor thing in the big picture, which is why we've seen Python implementations without them (Jython, IronPython). Performance-wise, yes, refcounting certainly isn't cheap, but you just do that and keep everything else C++-like, the overall performance profile of such a language is still much closer to C++ than to something like Python.
You can also have refcounting + something like `ref` types in modern C# (which are essentially restricted-lifetime zero-overhead pointers with inferred or very simplistic lifetimes):
https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...
It doesn't cover all the cases that a full-fledged borrow checked with explicit lifetime annotations can, but it does cover quite a few; perhaps enough to adopt the position that refcounting is "good enough" for the rest.
1 reply →
> In the limit, smart pointers for everything is just called "Python".
To be more precise, it's old Python. Recent versions of Python use a gc.
> And I am being walked hands handcuffed behind my back, alongside everyone else, into the Rust world with its comparatively anemic proc macro shit because the C++ committee can't be bothered to care about memory safety.
Out of curiosity (as someone working on static analysis), what properties would you like your compiler to check?
11 replies →
I do want C++ to be a safer language, but I don't think inheriting the Rust safety model is the way to go. It is in a way revolutionary but has major downsides like inability to deal with cyclic data structures without clumpsy workarounds.
I don't want to play with a plastic sword, just put it in a sheath.
The mentioned proposal isn't really that great. It basically tries to make C++ to Rust by blindly copying many its ideas. Many of them aren't strictly necessary to achieve safety in C++. There are different proposals for safety, which are way smaller and simpler than this one.
Which ideas aren't strictly necessary to achieve safety in C++?
Porting Rust enums and pattern matching isn't necessary (C++ already has std::variant).
Lifetime parameters aren't necessary, lifetime contracts may be implemented in a different and much easier way. This may be expressed in form of a function attribute, which may be calculated via constexpr code.
Special operators for borrowing just add more complexity. C++ already achieves same behavior by normal references (which may be mutable and non-mutable).
Introducing immutability by default isn't strictly necessary for achieving safety. C++ developers are already mostly fine writing "const" almost everywhere.
2 replies →
You can't convince me that 'safe c++' is not an oxymoron.
C++ will never be safe as long as its C root persists, it doesn't matters how much freatures you add on top of C++ to make writing safe programs more convenient.
You need to take off the "inherently unsafe" C root from C++, but it wouldn't be called C++ anymore by that point.
C+++ :)
C+-
Rust then?
From "The state of Rust trying to catch up with Ada [video]" > [awesome-safety-critical]
> rustfoundation/safety-critical-rust-consortium: https://github.com/rust-lang/fls
How does what FLS enables compare to these Safe C++ proposals?
Safe C++ draft: https://safecpp.org/draft.html