Just in case someone needs the reference, the onion uses '"no way to prevent this" says only nation where this regularly happens' as a reoccurring article at every major school shooting[0], to highlight the frequency of such events and the fact that nothing has really changed since the last one.
Thanks, I've had thoughts about making it a bit more elaborate (possibly involving large language models somehow to help synthesize what's going on into the right format, and so that it's not literally the same thing every time), but there's a charm in making it literally the same thing every time with the details swapped out. It points out the repetition to the level that all you need to do is swap out the details next time. This is all so preventable, but sometimes these things just happen and there's not anything anyone can do about them.
It's not even really benefits of guns are outweighed by people doing murders. All countries pretty much have some gun availability. In the UK where I am you can get a shotgun without huge problems for example. Also all countries have restrictions - even in the US I don't think you are allowed to stock up on M777 howitzers and ammo (British gun by the way). It's about having sane regulation.
The last comprehensive study on gun usage in the United States estimated that there are up to 2.5 million defensive uses of guns in the US yearly, most of which never involve firing a shot. They also found a correlation between gun ownership and lack of injury from violent crimes. Also you can own howitzers in the US, they just require special paperwork and a $200 tax stamp.
We have universal (depending on what that means) background checks for everything except private sales currently, you cannot go to a store and buy a gun without submitting one. Private sales are person to person and represent a rounding error in gun sales. Guns are a hot button topic and most people are uninformed so stats like "want universal background checks" doesn't actually amount to anything actionable legislatively because according to most gun owners, we have that, but many that don't own think its the wild west.
This isn't as clear cut of a case as you make it out to be. Britain's recently been on a path of overregulation bordering tyranny and limiting free speech. Canada is on a similar path. German green and red party politicians recently caught flack for trying to criminalize unpleasant critique. Press freedom and press independence are actively getting worse and Europe is setting course on a path of nationalism and conservative hardliners and there's an active war being fought on its borders. Islamic nationalism is on the rise and the issue concerning unregulated migration has a real chance to cause uprisings in the continent.
I do not like powerful guns in the hands of the population and I love the idea of a peaceful civilization without the need for violence, but you're living in a relatively short peaceful historic phase, which is just now starting to take a turn for worse again.
- UK sociopolitical problems caused by lack of guns
- Canada sociopolitical problems caused by lack of guns
- German sociopolitical problems caused by lack of guns
I think I can complete the rest of the thinkpiece on my own, with the help of ChatGPT. My prompt starts with, "You are a gun"
TIL almost every european country is in a state of tyrnanny. Also Yemen which is one of the only countries with somewhat similar gun ownership compared to usa (bit less than half as many guns per capita) must be the epitome of freedom and safety.
Every swiss that is issued the military gun (which is most) get a gun. They are trained by military professionals how to use the gun and hoe to store the weapon at home. It is for example forbidden and punishable by law, if something happens with your weapon, if you stored your weapons ready to shoot. You must remove the bolt and store it in a save, secured location. Using ammunition provided by the goverment must not be used, if it is used you will be punished. If you dont handle your weapon responsibly during trainig you may go to military prison.
So probably it probably not really compareable to how most people learn to handle a weapon in the usa.
Switzerland has very high rates of fun ownership, but their laws are far from lax. They are much stricter than the US.
You need a permit to buy anything other than a hunting rifle. You can't buy a gun if you have been convicted of a crime, have an alcohol or drug addiction or express a dangerous attitude.
You generally can't carry a gun except when going to and from hunting or a shooting range and you can't have the gun loaded in transit.
It's also compulsory for most male citizens to learn to handle a gun safely, something which the US doesn't require even if you buy a gun.
> You need a permit to buy anything other than a hunting rifle. You can't buy a gun if you have been convicted of a crime, have an alcohol or drug addiction or express a dangerous attitude.
...as opposed to the US? Do you think you can just buy a machine gun over the counter without any checks in the states?
Not an actual machine gun (a weapon specifically designed for automatic high rate of fire), no.
The US Supreme Court has repeatedly struck down reasonable restrictions for hand guns and rifles though, and seems likely to conclude that modifying a weapon to in effect become fully automatic is somehow OK. This creates a convenient gap which I don't think a reasonable person can believe is a mistake.
You don't need a permit to buy a gun, depending on the state, but you do need to pass a background check, show an ID, and if you wish to carry it outside your house, you probably need a permit, again depending on the state and whether you wish to conceal or open carry.
Although Switzerland does indeed have (by comparison to the rest of civilised countries) "Extremely liberal gun laws" and the higher deaths and injuries to match, it doesn't really compare to the US.
I've been doing programming for ~31 years in total and ~22 years professionally and at this point I have lost all hope that programmers at large will ever gain these mythic qualities called "self-reflection" and "introspection".
Truth is, these people are simply afraid for their cozy jobs, that's all there is to it. Derivative states of mind like Stockholm Syndrome and Sunk Cost Fallacy are quite normal to appear in these conditions.
On OP: I could not agree more. People always downplay their fuck-ups, that's sadly part of being a Homo Sapiens, but the lack of awareness is still both despairing and hilarious to watch.
And finally, C/C++'s niches have decreased but these people will not adapt, of course. Almost anything I've done with those languages 15-20 years can today be done with Rust. Or if you are on a tight time budget -- Golang, and you still won't lose too much speed.
But sure, "nothing can be done, these things sometimes happen". Sigh.
I would love to be able to use Rust in my professional project. Unfortunately, I am doing high performance scientific computing. Rust doesn't even come close to offer any good alternative to cross-plateform, cross-device (CPU/GPU) libraries such as OpenMP Target, Kokkos, SYCL, ... I believe we need Nvidia/AMD to take Rust seriously (I'm not sure it is even possible without unsafe everywhere) to be able to offer good libraries.
In my world, using C++ is the modern language, because most project are stuck with Fortran.
Also cross-platform libraries, if you want to be everywhere, from computers and phones to set top boxes to weird Japanese rtoses you haven't even heard of, Rust just won't cut it.
Fortunately there are other languages that are more available cross-platform than Rust with its tiny Tier 1 list.
Unless ofc you're contractually obligated to use vendors half-arsed kludget together patchy version of GCC of unknown provenance that they compiled with barely half C support, let alone other GCC languages.
I program MCUs as a hobby. I wish I could use something better than C. Even C++ with RAII would be better. But somehow, even C++ support is spotty, with unsupported features, broken debugging, etc. for seemingly no reason. And all device-specific libraries are written in C, so I'd have to write C++ wrappers for every little thing. Send help...
That's why I said "almost anything". I am aware that f.ex. kernel development and embedded work is still firmly in the C domain.
I am not evangelizing for Rust, Golang or anything in particular. I am evangelizing for periodically asking yourself "Am I still using the best tool for the job?" which most people never do.
It’s a cult, but you don’t have to join the cult. I use Rust both privately and more and more frequently professionally and I don’t really notice the cult community outside of smiling at it once in a while when it blows up on HN.
We’re mostly adopting rust to replace our C, to protect us from ourselves. It’s just so much easier to hand off these sort of projects to developers who mainly work with things like Java or C#. Partly because of the memory “safety” but also because things like enums work the way they expect them to being sum types, and so on. It’s also very clear when something is intended not to be mutable. The borrow checker is probably the biggest struggle, where with C, everything is a struggle.
Rust still has a long way to come though, and maybe it’ll never get there. I do think we’ll see an uptake as performance increasingly matters due to cloud costs and ESG. Right now though, I’d argue that unless you know why you “want” to use Rust then maybe you shouldn’t.
I saw your comment on an older C# thread in which you said (paraphrased) that C# is not bad, has nothing really stellar, and is just kind of bland.
If you could theoretically swap out the entire back-end of a programming language, and hypothetically you did that to C# by allowing developers to write C# styling and syntax that could be compiled to Rust, it would probably not be a big loss. The type primitives would be an apples-apples comparison at best, or "Rust is just better" if you really scrutinized the types closely. Where does that leave the rest of the language? A better regex implementation? Rust would probably win. A better GUI experience? Rust is speedily approaching usable APIs there at the same time Microsoft is trying to sunset the best they had.
Mostly agreed with your comment though I still have to remark that every community has zealots and it's mystifying to me why are people so annoyed by Rust's. So it's hard to agree that "Rust is a cult".
As you said, it's a pragmatic but also kinda niche language. I don't reach for it unless I can't do the job with others, easier and quicker to work with languages.
> ... every community has zealots and it's mystifying to me why are people so annoyed by Rust's.
Because they're the ones that we keep hearing from right now. When it was the Haskell zealots showing up every few days, they were annoying. When it was the Lisp zealots, they were annoying.
The C sphere is actually refreshingly free of zealotry (mainly I guess because there isn't such a thing as a "C community" and even despite C being the main attack target of language zealots - funny enough nobody complains about those pesky assembly coders and their hippie attitude towards memory safety lol).
The "religious zeal" was also an important reason why I switched back to C from C++ and why I don't have much interest in Rust. I can't quite stand the "holier than thou" attitude in.parts of those communities.
> This was an important reason why I switched back to C from C++ and why I don't have much interest in Rust. I can't quite stand the the "holier than thou" attitude in.parts of those communities.
This is 100% baffling to me. Let me explain.
1. Every single area has zealots. Yours included. And we're not talking only work. Every hobby area as well.
2. What the attitude of the most toxic 0.1% of the users of a thing is has exactly ZERO correlation with whether the thing is good and worth using.
3. By resisting only those 0.1% toxic zealots you are only demonstrating meaningless rebelliousness. As a supposed adult you should be immune to what are people hyping up and form your own opinion. INFORMED opinion. Not one based on the "many people praise it hence I, the intellectual, will stay far away from that obvious nonsense" stance.
4. Have you considered that maybe, just maybe, Rust is praised because it's actually good? Have you considered that the Rust community is not trying to cheat its way into your heart, and that the love Rust gets is justified by the people who need its features? Seems like you did not, and that's disappointing.
In other words, I have zero clue of your thought process here, maybe you can help me understand?
Back in my home town the VW Golf had an ardent fan base, yet one of my friends still bought one after he graduated. He didn't call the people who loved VW Golf zealots. He did his research and concluded that with his budget and mechanic skills the VW Golf is the ideal option.
I spent 20 years with C++ as my main language, and the endless and heated "style discussions" where personal.opinions are thrown around like facts were just tiring and a massive waste of time.
And it's such endless circular discussion where the extremists show up (I guess the equivalent in Rust is shaming projects that use unsafe, IIRC there have been quite a few dramas in the past). Shit like this is simply mentally exhausting, and in now 7 years of C as my main language I did not encounter this even once). In general C coders seems to be a quite relaxed, happy and tolerant bunch.
In the end I did seriously look into Rust for a time and decided that's not my thing and instead watch progress from the sidelines in case anything interesting happens in the language to give it another try.
What's quite obvious when watching from the outside is that it's almost always people with a crab emoji in their profile who are more likely to talk shit about C programmers (myself included in a couple of cases via subtweeting).
I usually just shrug it off and move on, because what else is there to do?
> In the end I did seriously look into Rust for a time and decided that's not my thing and instead watch progress from the sidelines in case anything interesting happens in the language to give it another try.
FYI I did the same because the kind of work that I do does not desperately need Rust's benefits.
But I'll always call out biased and prejudiced people and I don't care about what the HN group-think believes.
> I usually just shrug it off and move on, because what else is there to do?
1. Stop thinking that the zealots are representative of... anything at all, really. (I don't include myself in that group of zealots. I get ticked off by bias and firmly held preconceived notions. That's why I commented as much in the entire sub-thread started by me.)
2. Do your own research like you did.
3. Refuse to think about trolls and zealots. Which is what all of us as healthy adults in this attention-predatory age of the internet should do.
As a supposed adult you should be ok with the fact that not everyone will like your favorite toy and way of life.
I don’t use rust because I don’t have enough time in my life right now for discovering a new language just for the pleasure of it and even if I had, my real alternatives would be functional languages, not rust vs C++ which I use daily in a big project that has incentives stacked into C++ favor
If I responded in this fashion to someone who had already expressed concerns about a holier-than-thou attitude in parts of the community, I hope it would give me food for thought.
Just passing the ball? Yeah, I'd consider that + using a throwaway to be a set of circumstances that don't merit a response at all. ;)
I've already made my points several times. If you don't engage on the concrete arguments and are trying to be vaguely argumentative without substance then you're kind of polluting the replies.
Okay, and the direct version is that you responded to a general and rather vague comment about a holier-than-thou community by demonstrating in highly fluent detail exactly what that looks like in practice. To attempt a persuasive argument is by definition to engage in rhetoric. In the way you did so, specifically to persuade that the concern is unfounded, you behaved precisely as you sought to argue no one does. In short, you proved beyond doubt that your opponent's claim is valid. In rhetoric, there is no more abject form of failure.
Also, you behaved quite rudely as well as counterproductively - to the point that, if I felt any investment in the Rust community, I would now be asking you please to stop trying to represent it, at least until you can do so competently enough not to embarrass those you purport to defend.
If I found I'd erred as you have, it would bother me a lot. How you handle it is, happily for me, not my problem. But now at least you can't say you've never been told.
The point is that the guy who was bombarded by feedback that VW Golf is good did not go out of his way to avoid buying it. He did his own research, formed his own informed opinion, and didn't go against the grain due to misguided notions.
You are bombarded by feedback too, such that these endless discussions are just tiring and mentally exhausting, and improving a language by overfocusing on security is just a massive waste of time. (In some areas, it could make the difference between economic viability or not, or between possibility of explorative prototyping and mental exhaustion from friction during development).
I am assuming that you did your own research, formed your own informed opinion, and ignored the feedback nevertheless because you know who is right :-)
As a diligent programmer I research my tools and make my own conclusions when they are good and when they are inappropriate for the task at hand. Like everybody else should.
I don't even use Rust for a while now, by the way, because its lower speed of iteration was an ill fit for my contracting work. I love what it's doing but it is not a silver bullet (but then again, what is?).
...and by the way, mental exhaustion is pretty much a given if you are a pro. That's one of the reasons we are paid gobs of money.
As for the "feedback" you are alluding to, it's more like people throwing feces at me but feel free to disagree. None of them have addressed my questions except maybe one. They all rushed into snark just like you did. Even 1000 such comments are not interesting or informed feedback and can't advance any discussion.
I am still here and still open to discuss... with the people who bother to discuss.
I can't remember Linux zealots raving irrationally about C though (although when googling I'm sure something will come up). Topics like Wayland or systemd on the other hand, oh my...
They are alive and well in this sub-thread of mine, quite a lot of them even. :) Down-voting and never engaging because who wants their bias challenged?
But even if it was true (I'd contest it's not) can't you ignore it and judge the language on its merits? We are not teenagers for a long, long time now, we should be making up our own mind about things.
I have not done either. "Curmudgeon" is a "get off my lawn, kids!" grandpa btw. :)
I have not denied you anything, I implored you to ignore the zealots that exist IN EVERY ECOSYSTEM and judge the thing based on what it can actually do.
Please don't misrepresent what I said, that's not arguing in good faith.
Heh, this grandpa has written like 3x more python than C this year. And the C part was no choice - that was all I had on these devices.
Edit: from what I hear from my peers (translation: other programmers that I have coffee or drinks with), if I started a new server application today and I needed the performance of a compiled language, I should use Go not Rust.
I believe servers are where the propensity of C like languages to allow you to shoot yourself in the foot is the problem, isn't it?
Before the current "AI" hysteria, HN was full of "I've rewritten this thing that was working just fine in Rust". No mention of how it's better, has more features - or even has all the original's features - or anything about why you should use the rewrite instead of the original.
Am I supposed to use a tool just because of what it's made of, or because it solves a problem for me?
I don't need a 100% drop-in. Barely anyone does. I've observed at least 80% of all of the coreutils features are not used by 90% - 99% of programmers and sysadmins.
Ask people if they used all flags of `sort` and report back results as a test of my hypothesis.
> The right questions according to who?
This is tiring. I told you twice that I'd prefer you engaging in technical merits. You keep drawing attention to what is annoying you but you'll have to talk to your friends and family about that because I am not interested.
I don't see many CVEs in coreutils. Maybe one or two, in several decades? I do on occasion use obscure flags (or at least ones that are obscure to me).
I am getting tired of being misinterpreted, not of the argument itself because the argument ended several comments ago and the person focused on being a little rebel ("who gets the determine the right questions" is his favorite pet peeve apparently).
There is no argument currently, just people trying really hard to miss the point that was stated very clearly.
Mine was that some people needlessly -- and very immaturely -- rebel against using Rust because of something they saw on HN 5 years ago. There's no Rust zealotry here for a long time.
I chased after a few people asking them if they really tried it or they simply resist something because it's gaining popularity.
It is but there are other technical and non-technical merits too. "Security" doesn't trump all. If you need secure, turn off your computer.
I tried Rust and downloaded some projects that should be comparatively simple (e.g. text editor). "cargo build" downloaded and built about 500 dependencies. The Rust ecosystem had a chance to convince me, and it sure has some convincing results. But it wasn't my cup of tea.
If you included hundreds of dependencies to do what you can't easily do yourself within the "safe" framework, that may or may not be the language's or the ecosystem's failure. But the attribute "secure" for such a project is questionable. As NPM history or a certain guy or the recent events around the xz project illustrate well.
Rust only works for a few popular targets, but if it is just a hobby then Zig might be an option. C interop is pretty seamless, so you don't face the problem of having to reinvent the universe.
In my experience interop is rarely a language problem, lion share of time is consumed by reading the docs, testing if you understood the docs correctly, testing what's implied but not written in the docs and figuring out how to cope with idiosyncratic interface.
No, more people should be using memory managed languages like Java and Golang. Then educate and expose people to sum types and pattern matching. It is actually insane how people is still unconvinced about sum types. Imagine how insane it is to program without product types? That's exactly what it felt like.
I'm feeling my lack of academic training here, but I needed to make sure. When you say sum types, are you referring to enums, or is it a broader concept than that? The Wikipedia article was quite archaic but seemed to support my initial understanding that you're talking about enums.
Rust's enum is a sum type. The enum in C is just integers (again) wearing a hat for some reason. This may not be obvious, but if my enum in C seemingly has three possible values it... doesn't, it actually has at least hundreds of possible values, but only three have names - it's just an integer in a hat.
A sum type is an idea from type arithmetic. Suppose we have two types A and B, and we want to produce a new type from those, the most common provision in languages is to let you make a product type, it has all the values of A multiplied by all the values of B, this may be available to you as a named tuple, perhaps named a "struct" or "class" in your preferred language.
But what if instead we added these types instead of multiplying them? The new type has the values of A plus the values of B ? That's a sum type.
Suppose I have three types which resemble booleans: mood (it's either happy or sad), size (huge or tiny) and activity (either sleeping or eating)
A sum type of these three would allow me to make a "brief" of a cat as one of the six values, either as its mood, its size or its activity. The cat brief can be sad, or sleeping, or tiny, but it cannot be sleeping and sad [in this model] any more than a cat's size could be both huge and tiny. There are 2 + 2 + 2 = six values of the brief type.
In contrast a product type, maybe lets call that "state" of the cat consists of separate values of each of the three constituents, so the state of a cat might be (sad, tiny, sleeping) or (happy, huge, eating) or any other combination. There are 2 * 2 * 2 = eight values of this state type.
Just as an arithmetic is kinda crap if it only has multiply but not add, a type system is kinda crap if it can't make sum types. Where complicated hard-to-get-right hacks are used (e.g. C++ std::variant) these are often unsatisfying both ergonomically and in terms of delivered functionality, so hence the desire to have actual sum types in the language.
In Rust they are called "enum", elsewhere "tagged union", "discriminated union" or "variant" (under the hood, all of those are just a C-style union bundled with a tag field which identifies the active content of the union). The rest is language specific syntax sugar which makes their usage more or less convenient and typesafe (and sometimes more memory efficient, for instance a pointer|null type doesn't need the tag since the set of valid pointers doesn't overlap with null)
> (under the hood, all of those are just a C-style union bundled with a tag field which identifies the active content of the union)
Crucially that's not necessarily what's going on in Rust and (assuming it lands) won't be the actual implementation of C++ std::optional<T&> specialisation.
Instead the language can decide from the value which type it has. This is where Rust's Guaranteed Niche Optimisation kicks in. If we've promised the compiler that type T's values don't occupy the space needed fully, the GNO promises that sum types consisting of T plus one other value are the same size as T was. There is no "tag field".
In practice, the compiler can provide optimisations beyond the Guarantee. For example the compiler can see that OwnedFd (a file descriptor) has a niche so Option<OwnedFd> is the same size as OwnedFd (ie the same size as a C integer, typically 4 bytes), but it can also see that char has a huge niche. Many of the 32 bits aren't needed to store a 21-bit Unicode scalar value, so (although the guarantee doesn't apply) a sum type of a char and six hundred other named possibilities is the same size as just the char was.
Ah, I see you mention this at the end, I think it's worth highlighting much earlier, that the "tag" isn't actually a mechanically necessary part of such a type.
Just call them "tagged union" or "variant" and suddenly "sum types" are not so rare anymore ;)
...same with "struct", "record" or "tuple" vs "product type". Nobody calls them that except functional programmers and mathematicians, both quite rare specimen in the wider programming world, but nevertheless they are ancient and widely known concepts even among us "peasant coders" ;)
> Just call them "tagged union" or "variant" and suddenly "sum types" are not so rare anymore ;)
Nah, this is a false dichotomy. If a language doesn't have product types but instead resort to declaring variables separately, you don't call that "structs". Similarly, calling tagged unions a sum type is kind of misleading. They are both programming languages, I am sure I can do whatever I can do in A using B.
Why is a "struct" such a powerful concept? Because it is correct by construction. When I declare struct A, I have everything that A should contain. It is impossible to say, oops, I forgot about A::b. Similarly, a sum type as a concept is only useful when the abstraction is very, very solid.
Tagged unions or variants (in C and C++ respectively) is nothing like that. I have a variant A, I checked that that it is B, but oops, I casted it as C. Its your typical TOCTOU (or LOCLOU for line of check, line of use, I guess). std::optional is also like, same with pointers. Proper sum types, like Rust, it is literally impossible for me to get C by mistake.
Obviously, all of this minus some underlying implementation details, unsafe code yadda yadda.
Sorry if I sound aggressive, but I am just tired of "we have A at home, A at home (the most cursed shit)".
Does go have enums? Yea... just declare some global constants like so bro.
SomeEnum_A = 0
SomeEnum_B = 1
SomeEnum_C = 2
Yea..."enums"..
Edit: Oh how can I forget, we had this kind of issue just TODAY in production. No wonder I am so pissed off.
If that language you speak of is Rust or many GC more dynamic languages I'll agree. If you mean C/C++, frak no. They don't have "builtin safety" at all. Nothing that's opt-in is safe or secure.
What they suggest? What I and the discussed article claim is that safe code isn't written because programmers don't want it. CVEs aren't caused by desires, they are caused by unsafe code.
Many people suggest to start gradually migrating to either Rust or start investing much more seriously in formally proving C/C++ code (which is IMO a huge endeavor).
As I said in multiple other comments, I know there are valid cases for C/C++ where various factors prevent migration. I am not playing a little rebel revolutionary here, I am addressing the people who can migrate away but refuse to do so based on hand-wavy philosophy clashes (or my favorite petty rebellious take: "people praise Rust, I must resist using it!"). Petty stuff and I am pretty disappointed that people who bill themselves as "engineers" refuse to see objective evidence and hold on to only what they know.
Those are the people I address with my comment. Not the people who will be never allowed to migrate away a 2 million lines worth of C codebase. They have my deepest sympathies.
> Petty stuff and I am pretty disappointed that people who bill themselves as "engineers" refuse to see objective evidence and hold on to only what they know.
I think it is widely accepted that Rust is more safe. (There comes the NPM factor too so it's not entirely clear). The thing is just, you are excited about this technology, and you are equating "engineering" with "security". You are willing to pretend that other merits and factors don't exist, including ergonomics of iteration, or inertia. I tried writing my usual explorative Win32 code in Rust for an evening. Well, it was painful and I went back to do it the way that works for me, that is supported by all the official tooling, and that the official documentation is written in. I also can't see myself reading reasonable Rust code quicker than I can read and write reasonable C code in a year down the line. It's just too intricate, too clever, too condensed / abstracted and at the same time too verbose. Another time I went to download a couple simple projects (e.g. text editor) to dabble a bit with. But the stuff was too opaque and had _hundreds_ of third-party dependencies, and I couldn't understand it well. So I lost interest.
Choice of language and ecosystem is an economic matter. They get chosen based on what one knows and what one wants and how one evaluates the possibilities. "Security" quite frankly is not the most important of concerns in most situations, and for a good reason. I frankly am not getting paid in finding the nicest or "most secure" way to write a piece of code, but to get it done. I am not interested in following the development of the hundreds of dependencies of my Rust project, and to change my data structures when they learned a better way to design the API to those "safe" data structures.
But you are seeing only "security". Well, it's most secure to just shut your computer off. So much for "objectivity". Maybe you _are_ the zealot!
> The thing is just, you are excited about this technology, and you are equating "engineering" with "security"
I do no such thing. I am not at all excited about Rust in fact anymore, I just learned where it excels at and I know when to reach for it.
> You are willing to pretend that other merits and factors don't exist, including ergonomics of iteration, or inertia
I have literally just responded to you before this comment where I made it clear that I stopped actively using Rust due to slower speed of iteration -- and that is said in another comment as well (including the inertia or lack-of-choice factor).
Can you please not misrepresent what I said? It's clearly written in at least two places.
> Choice of language and ecosystem is an economic matter. They get chosen based on what one knows and what one wants and how one evaluates the possibilities.
Which agrees with my "right tool for the job" take elsewhere in the thread. We're aligned.
> I frankly am not getting paid in finding the nicest or "most secure" way to write a piece of code, but to get it done.
Yes, and that explains why the programming at large is always teetering on the verge of ruin and stuff is barely working and is kept together by goodwill and spit. Though obviously worker bees like you and me can't change that reality for now. I have partially made my peace with that fact but not entirely; hence I reach for Rust every now and then.
> But you are seeing only "security". Well, it's most secure to just shut your computer off. Maybe you _are_ the zealot!
You seem to have gotten quite worked up and I'll ask you to stop. When I told you that I am open to discussion in a previous comment I was genuine.
Both Microsoft and Google said that from 60% to 75% of all C bugs are memory safety problems -- not my words, not my research, but that of two of the largest IT corporations out there.
That is proof. That is objective info. We can bikeshed and throw feces at each other until the end of time but there are people who got out there and gathered the info.
I refuse to be viewed as a zealot simply because I want to attack the lowest hanging fruit in terms of bugs and security vulnerabilities. No, that makes me both a pragmatic and a guy who is no longer willing to live with the broken status quo.
And I'll not agree with your polarizing take that "the only security is shutting your computer down". That's nonsense. You are simply not motivated to advance anything but your career. That's your right, surely, but at the same time it makes you dismiss any well-intended discussion about the current state of our profession and how can it be advanced further. You dismiss stuff off-hand and then you blame me for being a zealot. Not acceptable to me and I'll not take it.
So try and calm down and read better. We in fact agree on much more than you think but you are not seeing it because you seem to have formed an opinion of me before you even started writing.
THIS, sadly. Though it'd be more accurate to re-phrase: 's/just don't want to do it/have other priorities, or are stuck in organizations with other priorities/'
And it doesn't need to be Rust, as the anti-seat belt folks always are quick to complain about, plenty of systems languages since PL/I and NEWP days have bounds checks by default.
Back in the days we were arguing for Ada, Modula-2, Object Pascal on Usenet, we were straitjacket programming advocates apparently.
And yeah I am gradually giving up on arguing with people who are extremely biased but point at me and blame me for being biased. Seems there's no win.
I actually regret engaging so thoroughly in this thread but once started I figured I'll not budge and will hold my ground. I am anti-group-think that way.
I haven't engaged in such threads in a while and I think the next time around is going to be months in the future. We'll see.
Eh, Rust would be fine if not for the fact that it's too opinionated.
Unfortunately you can't just have Rust's safety checks, without opting into restrictions that Rust designers force onto You that aren't inherent to safety checks, but more because 'that's a better practice (according to us)'.
And also, easy and fast iteration just isn't there, both because of borrow checker restrictions and compile times
C/C++ being non-opinionated is the main source of the security vulnerabilities.
Let's face it, it felt good to be a lone cowboy carrying a lot of responsibility and knowing what you are doing. I was there myself and I'll admit the ego trip was awesome.
These times are long past and naturally, people refuse to adapt.
> Unfortunately you can't just have Rust's safety checks, without opting into restrictions that Rust designers force onto You that aren't inherent to safety checks, but more because 'that's a better practice (according to us)'.
Show me something that does better and I'll switch tomorrow. But don't tell me C/C++ are better -- they are not. Too much freedom leads to CVEs literally every month somewhere and that's only because we don't have better vetting and checking tools, otherwise I'm sure we'd be getting one every day for a while.
> And also, easy and fast iteration just isn't there, both because of borrow checker restrictions and compile times
I agree on that, that's why I mentioned Golang. Most of the C/C++ systems I worked on around 15-20 years ago didn't need the close-to-the-metal speed because at least 90% of their time was spent on I/O... frak, even Python would have done well there. And Golang is times faster. It's a very nice compromise if you want to be productive and don't care super much about CPU speed efficiency.
> C/C++ being non-opinionated is the main source of the security vulnerabilities
This. "Undefined behavior" is such a terrible way of thinking. As is the "we can assume in the optimizer that UB does not happen and then eliminate code on that basis", which allows the compiler to introduce bugs that only appear at certain -O levels.
It took decades to get them to define arithmetic as twos-complement.
> It took decades to get them to define arithmetic as twos-complement.
I'm not sure this is right? IIRC C++20/C23 require two's complement representation for signed integers but generally leave other behaviors (including signed overflow) the same.
I’d say the biggest problem of interpreted, JIT compiled, and GCed languages is not the speed; it’s the RAM use. I agree that quite often we don’t need the speed of close-to-the-metal. But there is something wrong with most programs eating tens or hundreds of megabytes, without doing much.
And I agree on that. My favorite Elixir's runtime (Erlang's BEAM VM) still has some subtle problems with holding on to big(ger) binaries (strings) that requires very specific code be written at the green thread boundaries and it can get pretty maddening if you don't get it right -- which is not easy.
Golang I hear is doing much better btw. But you still have to be wary of its footguns i.e. leaking goroutines.
Go is doing much better on memory use because 1) it is AOT compiled, 2) it tries to allocate as much as possible on the stack (escape analysis), 3) it supports value types (the items of an array and the fields of a struct are contiguous in memory). But it's still a GCed language, which generally means a slightly higher memory use, controlled by $GOGC, to not spend too much time CPU time on garbage collection. Overall, Go is an excellent tradeoff for most applications.
There are restrictions out on You by the borrow checker to ensure safety, and then there are restrictions put on You by rust design team 'just because'.
Again, the former are fine, it's the latter I have a problem with.
In order for me to agree on the "just because" part you'll have to give some examples. What made you think they are arbitrary? And how did they prevent you from doing your job?
Comment above, mentioned borrowing while structs instead of borrowing memory.
I believe this was once discussed under term 'partial borrows', but the "idiomatic" aproach is to 'just split your structs'.
Which isn't really a good aproach to structuring codebase, it's just to appeal to borrow checker inflexibility.
Lack of global scope.
Lack of function overloading.
> Comment above, mentioned borrowing while structs instead of borrowing memory. I believe this was once discussed under term 'partial borrows', but the "idiomatic" aproach is to 'just split your structs'.
You're mistaking "idomatic because it's the only way" with "idomatic because we say say so". There is currently no way in Rust to specify the granularity of a borrow, so we're stuck with splitting your structs to get around it.
Part of the problem is that it's a hard problem to design around. It can not be done automatically by the compiler, because it would result in changes in the implementation being changes in the type signature. For example, say we have this function:
pub fn foo(&self) -> i32 {
self.a + 5
}
The granularity is borrowing `a`. If we then change it to this:
pub fn foo(&self) -> i32 {
self.a + self.b
}
The granularity of the borrow has changed in a backwards incompatible way (it now includes `b`), but that change is not reflected in the signature. It's the same reason why the compiler refuses to infer signature lifetimes from function bodies now.
You could, of course, say that we can allow the programmer to specify it manually:
I would say until C++98, C++ used to be more opinated, one of the reasons many of us went with C++ when given the choice, wasn't OOP features, rather the security improvements over bare bones C, with compiler provider frameworks.
Then eventually C++ got invaded by C expatriates, and writing C with C++ compiler idioms increased instead of going away.
It is like giving Typescript to groups of folks that insist on using any all over the place.
Actually I have good-ish memories of the early `boost` (we're talking 2003 - 2006) and some of the `std::` libraries in C++. They got the job done fine and were not in the way. So yeah, agreed.
Are you willing to die on this hill? I remember an HN post a while ago where both Microsoft and Google said something like 65% of the bugs in C code were related to memory (un)safety.
> Show me something that does better and I'll switch tomorrow
Frankly this is a very bad decision. Because now you have C code, Rust code, and yet another language's code, and you're left with a mess that you have to integrate too.
Obviously I was demonstrating that I don't shill for Rust in particular -- I simply believe C/C++ are not cutting it anymore. Rust is not perfect but it solves a sizeable chunk of their problems, that's all.
Most programmers don't have any opinions, so if they use an unopinionated language, they end up using patterns that opinionated people use. So it's better to have one source of truth for opinions, so that we don't end up using the "wrong" opinions of people who talk more than they think.
Compiler/language people are also just "opinionated people" though. Some have good opinions, some have bad opinions. In the worst case you have opinions which are the result of a 'design by committee/community' process.
Single source of truth of opinions can be challenged and changed if one's arguments are good enough. The benefit is that it's easier to see the advantages and disadvantages for those opinions, because they're all in the same place.
This is in contrast to C++, where one organization creates a set of guidelines, another organization creates another set of guidelines. Valid arguments of critique in one organization are not seen in the other.
Single source of truth is also beneficial to compiler authors as well, because they get more feedback how the language is used and why.
There's a massive Terra Incognita to explore between Rust on one side and Python on the other side (just to pick two extremes).
It's not "2 out of 3", it's a triangle where a language can pick a sweet spot anywhere within the triangle (and ideally, it's not a "sweet spot" either, but more like a "sweet area" where the programmer can pick an actual spot within that area defined by the language).
That sort of extreme flexibility simply does not exist. I mean it does but then you are firmly in the dynamic languages territory and you are forgoing any hope for close-to-the-metal performance.
IMHO it does and its not restricted to dynamic languages (like JS or Python), look at this Zig function signature for instance (just an example from my current dabbling):
In practice this looks and feels like dynamic typing, yet when looking at the compiler output it still resolves to optimal code (since it's "compile-time dynamic typing" not "run-time dynamic typing", but the difference in practice is surprisingly small).
Well you can make OCaml and Rust look like dynamic typing as well by omitting type signatures and squeezing the type inference engine as much as you can but I was under the impression that you have more asked about something that is very relaxed in terms of upfront requirements and be able to tighten it up later?
That's why I claimed that no such language exists.
I was thinking more in terms of "language surface" but it didn't come across, C and Zig have a fairly small language surface (Zig a bit bigger than C), simple language primitives that can be combined quite freely and without much restrictions, but at the same time not carrying a lot of semantics the compiler could use to ensure safety (ignoring the "sloppiness" design warts of C though, like implicit type conversions, allowing accidential uninitialized data, or inverted defaults (mutable vs immutable) - these things are obvious problems but cannot be easily fixed in C or C++ because of backward compatibility requirements - they have been fixed in Zig though).
Rust is quite the opposite, more primitives that carry semantics (most of those in the stdlib though), a stronger but also more rigid type system, but those are pretty much needed for the compiler to guarantee safety.
The million dollar question is of course, can there be a more relaxed Rust with the same safety and performance guarantees, maybe by "squeezing the type inference engine" even more (and letting Rust look or somehow extract information across crate boundaries)? And do Rust programmers even see this as desirable, or are they mostly comfortable in their current sweet spot of the triangle?
I agree that your million dollar question is very good and relevant. Rust can definitely be improved -- async is sticking out as a sore thumb still and it requires a lot of ad-hoc knowledge that's not at all intuitive -- but I'd still venture to say it does pretty well in many areas.
Rust absolutely is not the end state of programming languages but I feel in many ways it's quite ahead than most of everything else. But yes, we still need something a tad better than it.
Again, restrictions that are forced you for a price of safety are one thing.
But what I'm complaining about are restrictions that don't have to be there to get borrowchecker working, but rather are there because designers arbitrary decided "it's better this way".
All AFAIK, since I only dabble occasionally in Rust:
The borrow checker works on "struct granularity", but it would be much more flexible and convenient if borrowing would work on memory location granularity (for instance passing a struct reference into a function "taints" the entire struct as borrowed, even if that function only accesses a single item in the borrowed struct - this 'coarse borrowing' restriction then may lead to all sorts of workarounds to appease the compiler, from 'restructuring' your structs into smaller pieces (which then however may fit one borrowing situation, but not another), or using 'semantic crutches' like Rc, Cell or Box.
There are also related restrictions about function call barriers. AFAIK the Rust compiler cannot "peek into" called function bodies to figure out what's actually going on inside those functions (and that information would be very valuable for fine-grained borrow checking), it can only work with the information in the function signature.
Again, disclaimer: take this with a grain of salt since I'm not a daily Rust user, but this is how I understood why Rust feels so restrictive.
> The borrow checker works on "struct granularity", but it would be much more flexible and convenient if borrowing would work on memory location granularity (for instance passing a struct reference into a function "taints" the entire struct as borrowed, even if that function only accesses a single item in the borrowed struct - this 'coarse borrowing' restriction then may lead to all sorts of workarounds to appease the compiler, from 'restructuring' your structs into smaller pieces (which then however may fit one borrowing situation, but not another), or using 'semantic crutches' like Rc, Cell or Box.
That's valid, thanks for pointing it out. I seem to recall the team lately mentioning they are starting to consider fixing that. And yes that's a real productivity killer, happened to me as well in the past.
> There are also related restrictions about function call barriers. AFAIK the Rust compiler cannot "peek into" called function bodies to figure out what's actually going on inside those functions (and that information would be very valuable for fine-grained borrow checking), it can only work with the information in the function signature.
I don't think it's so much "can not" as it is "will not". Allowing the function signature to be determined by the body can lead to accidentally breaking callers by changing the body.
That, at least, is consistent with other parts of the signature: the input/output types and how the lifetimes of input/output references are related.
I don't disagree btw. As a contractor I have found myself very often in a situation where Rust's slower iteration simply didn't work for me so I got back to Elixir and also relearned and started getting proficient in Golang.
Rust's slower iteration only disappears when you become a pro as you said and that's my main problem with it. I simply can't invest as much time and effort for free.
Rust is just a different language. It's not C-like or Java-like plus checks or anything like that.
It's a value oriented language. Variables mean something completely different than in any other common language. Everything is about the values and where they are kept at the moment.
This is one possibility. Have you considered the other, that you're the old-man-yells-at-cloud variety of narcissist?
Hence why you choose to interpret things as everyone (except you) is defective. Everyone (except you) is laughable, completely lacking in self-awareness, refusing to adapt and be and do as they should (according to you of course).
Because they're all lesser than you! That's why. You write Rust. So obviously, you're so far above them. Like a God looking down at monkeys.
Couldn't be reasons like inertia, or lacking the time, or not having the budget to change, or being too tired to learn, or any other such thing that'd let them be equal to you but just with differing priorities.
No, because then you wouldn't get your narcissistic supply, allowing your delusion you're better than others, rather than a man distracting himself from his own failings?
> Couldn't be reasons like inertia, or lacking the time, or not having the budget to change, or being too tired to learn, or any other such thing that'd let them be equal to you but just with differing priorities.
This is already included in the "almost anything" expression and you are the 4th person deliberately (or accidentally?) not noticing it.
There are valid cases for C/C++ both on technical merits and business specifics. I have not denied that.
---
The rest of your comment is just projection borne out of your faulty assumptions about my comment and it's thus not interesting at all.
> This is already included in the "almost anything" expression and you are the 4th person deliberately (or accidentally?) not noticing it.
I genuinely think that :
1/ this field is dominated by a disproportionate amount of people with autistic traits
2/ their ability to reason only functions in the narrowest sense and their grasp of language (takes everything in the most literal sense, thinks in extremes, prone to putting things in boxes, have a very, very strong attachment to their routine and are unable to ever leave the comfort zone they constructed) makes any attempt at communication beyond painful.
I have come to not even bother replying to people who are unable to understand human words such as when they interpret "most" as meaning "all" or "rarely" as "never" as it's one of the telltale signs that it is going to be extremely unproductive.
This phenomenon is the cause of most pains and drama. Once you start to see how this pattern develops you understand the true cause of the endless bikeshedding, of why even the idea of having a code of conduct can raise endless anger and storms and so on. You're touching a comfort zone so the temper tantrums are thrown. The routine has been built and it must continue until the end of times.
If there's any field in this world that is in need of more neurotypical, emotionally stable adults, this is it.
Or maybe, just maybe they correctly interpreted "most" as "more than half" and "rarely" as "decidedly less than half", and actually disagree with the statement as is. And what can I say, "reasons like inertia, or lacking the time, or not having the budget to change, or being too tired to learn, or any other such thing" sounds exactly what almost anybody is confronted with -- so it doesn't exactly seem like just an _exception_ to the set of "almost anything".
But it's nice to add words like "autistic", "thinking in extremes", "painful", etc. to terminally bash on those people who are wrong and just can't learn...
Or maybe, just maybe, I explicitly agreed with the real-world limitations up-thread but now you are just looking to pick a fight because me agreeing with stuff does not fit your preconceived notion. :)
But, by all means, go on, I can only presume you are bored.
You obviously need to perform the correct rites and pay your homage to the blessed machine spirit or the Omnissiah will not permit your code to compile.
> "No way to prevent $THIS" say users of only language where $THIS regularly happens
A weird psychological quirk I've noticed (of myself, and others) is we'll often exhibit a sort of 'programming language xenophobia', where we apathetically accept (or don't even notice) unpleasantries of our language of choice, yet be quite averse to the unpleasantries of other languages.
Maybe it's due to sunk cost; time/effort has already been spent finding work arounds for or adapting to the warts of our native tongue, whereas doing so for unfamiliar languages would require additional effort.
I would rather have unpleasantries that make the language safer vs unpleasantries that make it more vulnerable. Especially when the unpleasantries in question don’t even make the language easier to use.
It would have taken you less time to look up -fwrapv / -ftrapv / -fsanitize=signed-integer-overflow + -fsanitize-undefined-trap-on-error than write out that misleading dialog. :)
Last time I checked ubsan was a few years ago for a small program, and I've read stuff about it not being suitable for anything outside development (more like a valgrind complement than a release option) because of how it messed with environment variables and linked libraries or something, so I might not have the full picture.
C is more likely to define wrapping arithmetic. Wrapping is defined as undefined for compatibility with MIPS processors that support checked arithmetic.
There’s probably a large selection bias at work as well – people who care about those specific unpleasantries will avoid that language in the first place.
This is definitely a thing I recognise in myself, a year and a half of writing Scala daily has made me much more prejudiced against Java than I was before.
Alternative headline should be "But I have been taught that using C++ makes me the better programmer" because the stereotypes of echo chambers on the internet raised a lot of unreflected programmers to be this way.
There is a place for C, where there's no alternative. But that place is where 99% of programmers never work, because they are not doing kernel nor firmware development (which, in the meantime, also has a lot of support by and for memory safe VMs and languages).
The issue I have with this narcisstic fatigue (similar to the author's point I assume) is that there is no reflection when they fuck up a codebase.
The best code is the code that is safe and easy to read, and doesn't need to use "clever tricks" that beginners cannot understand.
If you are using some tricks for type casting to implement your ideas into code, you probably should not write code.
Code should be dumb and easily maintainable. If it is not, you made the wrong choice for the programming language.
Kernels have been developed in safer languages already before C became widespread outside Bell Labs, it is a myth that C is even required for that, other than historical baggage.
Especially when one adds how many "low level programming" idioms for C are, as far as I understand, undefined behaviour in C. Like assigning an address to then use as pointer to physical memory...
Which is extra visible when one looks at original UNIX sources and its many short assembly bits in separate files to handle bits of direct hw manipulation.
It's not UB. It's also not covered by standard - it's implementation-specified. What will happen is dependant on decision of compiler writers.
It is, however, not the only way to write to memmapped registers.
The original C way of doing so was to use an assembly function wrapping the actual act of reading/writing (honestly, better than doing the above, as it helps making it very explicit how the write will happen as well as abstracting any details like needing to add a barrier or whatsoever), the other way was to specify the symbol with address of the memmapped register in assembly, and link resulting object with C code.
A C implementation is, AFAIK, free to refuse the literal addresses used as pointers and pass as ISO C.
What I mean is, most compilers won't generate a function call or an additional indirect memory access for *(111) = 222;, unlike your spec-compliant alternatives.
This is, IMO, the problem. Sometimes we just want a more ergonomic way than inline assembly in a hot loop (and also we'd like to to pretend its portable). The spec does not have an answer to this.
So, unless all C compilers in the world actively sabotage this usage (like how Go did to map traversal orders), your spec saying this is "implementation defined" have no impact at all. All C compilers are bound to implement the same intuitive but completely-not-enforced-by-spec behavior. Because if they don't, people just use something else.
I don't know if this particular example is UB or not, but the dichotomy here between 'defined' and 'not defined' is a false one, as C also specifies some constructs as having 'implementation defined' behavior. The behavior of such constructs is not defined in the standard, but is also not 'undefined' in the special sense of 'undefined behavior'.
> Is your whole post even related to this article?
I think they were just reiterating TFA message in another way: Don't expose yourself to the pitfalls of C when the actual power of C is not really needed.
> There seem to be no casting issues involved in ...
Maybe go to http://osv.dev/list and search for OOB or Out of Boundary errors instead to make a study on whether this regularly happens or not? Especially when parsing arbitrary strings into a struct?
I'm not sure whether or not you got my message to prefer any programming language over C/C++ or whether you're trying to ignore that on purpose?
>But that place is where 99% of programmers never work, because they are not doing kernel development
Certain embedded targets are also legitimate use cases for C. For example, I am currently working on a project using an 8051 microcontroller. Aside from using assembly – which obviously isn't safe either – there is no practical alternative to using C. Rust may be making inroads for 32-bit targets, but will likely never be able to target an 8051.
We now have enough resources to do this. When C was created, we had to do those tricks to have good performance. Currently C is best used for constrained devices, where sometimes you need those tricks.
> If it is not, you, yes ... you, made the wrong choice for the programming language.
Or your project manager or CTO, or some other stakeholder.
C is portable assembly. Don't use it unless you really must.
Yes I know people want to replace C with Rust, no it won't work because Rust is not assembly, yes it can be used to replace anywhere between 90% to 99% of C and it shouldn't even be too hard. (Unless your embedded device manufacturer doesn't care, which of course they don't.)
Unfortunately, it isn't quite this, and many of the instances which people use it for this are actually undefined behavior; there's a hinterland of "things C compilers do" which are used as portable asm but are not part of C because they are UB.
I sometimes wonder if it would be feasible to define an actually portable typesafe macro assembler.
Only if you mean K&R C, where C was mostly a portable macro assembler, calling into Assembly code, written and compiled via an external assembler like in the first iteractions of the UNIX rewrite from Assembly into C.
The Lions book is a good example of what that C used to be like.
> The issue I have with this narcisstic fatigue (similar to the author's point I assume) is that there is no reflection when they fuck up a codebase.
Forgive my bluntness, but do you even know any C programmers? The ones I know are not at all a homogenous group (there isn't even anything resembling a "C community" - and IMHO that's a good thing btw).
> The best code is the code that is safe and easy to read.
These two things are not really related.
- Rust code is safe, but typically not easy to read
- C code is unsafe, but typically easy to read
...as a counter example though, C++ code is unsafe, and typically not easy to read.
Of course "readability" is entirely subjective too. Seasoned programmers are typically blind to the problems of their language of choice (and that includes C's sloppiness, and Rust's readability). Language beginners typically stumble over problems that experienced users of that language wouldn't even think of.
> Code should be dumb and easily maintainable.
Well, obviously, but see above, one programmers 'dumb and maintainable' is another programmers 'unmaintainable complicated mess'. IME it's harder to write code that's 'dumb and maintenable' in languages that nudge the programmers towards sugarcoating the program logic in high level abstractions than in "simple" languages like C, Go or Zig, because you don't just need to know the language, but also understand the high level abstractions the original author came up with (and which might have been a good fit at the start of the project, but not 3 years later when requirements have changed and the original programmers have long left for greener pastures).
IME it's not 'narcissism' that makes programmers pick C, but the incredible flexibility of the language, combined with being quite predictable what code will be generated (yes, optimizer passes do complex things, but after a while you'll develop an intuition for what the compiler will do, verifiable via godbolt).
Also for instance, look at the hoops other languages are willing to jump through just to get close - but never fully match - what's possible with simple text replacement in the C preprocessor (an incredible hot take, I know).
Absolutely not, modern C code (eg C99 or later) looks a lot different than C89. One problem is that the C stdlib is stuck in the C89 era, but at the same time most of the stdlib isn't all that important for writing C code).
Some of the HN discussion about whether "new projects in C should be allowed" is moot: Fluent Bit was imported into git in 2015 [0] (a few months before Rust's first public release), and may be considerably older than that for all I know.
I suppose incidents like this actually do give a reason to "rewrite it in Rust", when "it" is "widely deployed infrastructure written in C". OTOH, I'm sure there were plenty of non-memory-safety bugs introduced and later fixed over the years, and rewriting in Rust will recapitulate that subset of bugs.
People slipping backdoors into stuff are no doubt super enthusiastic about Rust both for the opportunity for new anonymous nobodies to rewrite long stable and proven tools as well as the dependency ecosystem that tends to blindly pull in multiple different entire HTTPS/TLS stacks into anything but the most trivial software.
I don't buy it. Rust has a really good track record on attracting more people to read and modify the code, which isn't what you want if you're hiding backdoors in the code.
In decades of writing C (sometimes as a hobby, often for a lot of money) I'd guess I thought "These errors when I wrote bugs in my program are crap, somebody should fix it" maybe once per month on average. But a C compiler is very intimidating code, subtle and hard to even build from scratch let alone contribute to, so I never attempted to make such changes.
In only a few years of writing Rust (none of that paid) exactly twice I've thought "Man this compiler error diagnostic isn't very good, somebody should fix it". The first time I asked on Reddit, and I was informed that I wasn't the first to notice, the fixed diagnostic was in nightly Rust already. The second time I found the diagnostic and I just fixed it, compiled first time, wrote a new unit test, checked that passed, wrote a pull request. Landed it. Then I wrote a HN comment, a reader found a bug in my diagnostic, so I fixed the original code, and wrote a new PR which also landed. If Rust has told you that instead of 'X' when you needed a byte, you should write b'X' because just 'X' is a char not a byte - that's me, that's my small fix. [Before the fix 'X' wasn't legal here, of course, but the diagnostic wouldn't suggest what to write instead]
I'm not sure how modifying the compiler is relevant to the point. I think it's the general trend that early in languages lives its much easier to contribute to the tools, after decades of amassing improvements (such as yours!) they tend to become less accessible.
But regardless, the "rewrite in rust" advocacy has created a significant opportunity for projects created by single people, without outside review and often without significant domain expertise (at least where they are slavish re-implementations of existing code), to be proposed as replacements for longstanding stable tools. Whatever the merits of that chance it's also dream for someone looking to introduce new vulnerabilities. Even where the replacement itself is reviewed it will usually come with a massively expanded dependency footprint which isn't.
The compiler is illustrative. A large piece of Rust software, nevertheless easier to read and contribute to when compared to similar software in the same category.
I had someone on Reddit r/webdev try to convince me that 'this' was not a mistake but a powerful language feature. A small glimpse into the mind of JS fans.
Sounds like something any programmer would say about their preferred language. Can't say you don't hear similarly crazy things about C, or C++, or Java.
True. But it's generally only common with older C-based languages where the goal was packing as many features as you can instead of high level design aimed to guard software from inexperienced overeager devs.
Yes, it's functions vs methods. You can make this explicit like in Python, you can make it implicit but have two kinds of methods, instance methods and static methods like in C++/C#/Java.
And you have JavaScript were all functions have an implicit this ...
Oh no ... a bug in a C program. This easy bashing on existing C programs is getting boring and annoying.
Write a new userspace program? Use anything else, all language shave flaws so pick one which supports the features you need. Want to quickly write something because you are not allowed to rewrite the entire ecosystem you need into a new language since the project will go massively over budged: Use what you can and what's available and accept the risks, which is the 99th percentile of software.
Free Pascal and Lazarus which is a GUI built on it support strings that don't require manual allocation and are counted and reference counted. A huge amount of grief would go away if that library could be supported in the Linux kernel somehow, and all of the string parameters in system calls ported.
> a vulnerability in HTTP parsing code that allows for heap corruption and arbitrary code execution by making a HTTP GET request with a megabyte of the letter 'A' in its body
You mean a buffer overflow? Why write so technical then dumb down something that's pretty obvious.
They're being satirical. People usually berate my posts because I have cartoon characters for Socratic exchanges to teach people things like Kubernetes, claiming that is "unprofessional" or something. These people are sarcastically berating my post for NOT using that Socratic system.
IMO GGP wasn't being sarcastic, but GP maybe was. Anyway I keep my thought: if a workplace, especially if in Tech or Tech-adjacent, sees furries as NSFW, it's a very boring workplace and I would run away from it at the first possibility.
No No No, I genuinely love both your Socratic exchanges and the furries characters that illustrate them. (although this is article is firmly Aristophanes, again, top notch work)
I don't hold with the "I'm not going to open a link on HN from Xe at work" bollocks, because I know its going to be a gem, moreover, I'm not a fucking prude.
If one can, at work, open the daily mail, "listen" to music videos, or read celeb gossip sites at work, then you can 100% look at computer using anthropomorphic animals.
Plus ever since I read your article about abusing S3 into a message queue, I've started using 18th century engravings of gargoyles, statues and classic sculpture to aid my presentations.
In summary, I love you work, I wish you to continue making it, and please don't take my comment as sarcastic. As I said before many months ago, this is what the internet was designed for, long may it continue.
Being a furry is and always has been a sex thing for the majority of the fandom. Some furries will vehemently deny this but we have receipts going all the way back to the 1970’s: https://en.wikifur.com/wiki/Vootie
Anime is not inherently sexual as a medium but has a well-deserved reputation for being associated with creeps and perverts.
> Being a furry is and always has been a sex thing
I mean you could argue that about Emos, or Goths. Its not really true.
I'm sure sex is a large motivator, but you can't be doing sex all the time. When a Goth is dressed up all Goth-y its not because they are horny right now. They are just wanting to look good.
I imagine its the same with the furries, but the difference is, the furries are the butt of most jokes
You can’t just say “No, you’re wrong.” And expect me to change my mind??
Both being a goth and being a furry are about way more than clothing and appearance. Goths don’t really have anything to do with furries. I don’t know why you’re bringing them up.
Every furry I have met in real life thought it was a sex thing. Every normal person from the outside looking in thinks it’s a sex thing. Just look at the history of furry magazines and subculture and it is mind-numbingly obvious that it is a sex thing.
Even if it wasn’t a sex thing, would you want to discuss it at work knowing 99% of people will think of it that way?
What about good-looking people that enjoy it and dress more "provocative"? Reading some news with people in the gym or on a red-carpet is NSFW as well?
Oh course its a sex thing, but its also a lifestyle. My colleague is furry adjacent. I don't think they have a fur suit. However the rules and culture of furries are frankly quite fascinating. Like why are most furries dogs(or dog like)? why not camels, birds, monkies or fish?
My point is, there is an entire culture, just like emos, just like goths, and to me, that is fascinating.
So yeah, we do discuss it at work, and no I don't care overly much, because I don't work with 14 year olds.
No I'm not. I expected that there is some furry or anime girl visible when i click on that link. This is the stuff i do not want to have on my screen when there are coworkers nearby.
I also used to think I had this issue when reading your blogs at work. Turns out, nobody really cares and if they do, a quick explanation suffices entirely. I no longer care as well.
Your imagery is part of who you are as a writer, and it's part of your work. People need to take it or leave it.
The headline is misleadingly focusing on a soundbite out of the full quote.
"It's a shame, but what can we do? There really isn't anything we can do to prevent memory safety vulnerabilities from happening if the programmer doesn't want to write their code in a robust manner." -- Some (uncredited?) C programmer.
Does C have more footguns as a low level language? Of course. That's part of the freedom of bringing only the baggage a project needs. Sadly, like many dangerous or sharp tools, incorrect use will lead to harms.
If someone has a choice, a safer more modern language can accommodate less skilled practitioners.
It's a deliberate echo of the famous Onion headline about America's absolutely disgraceful pretence that it couldn't do anything about all the shootings.
> If someone has a choice, a safer more modern language can accommodate less skilled practitioners.
This is the usual mistake. It's not a "skill issue". Footguns are a design mistake, they're much more dangerous than necessary hence the name. As a result the practitioners accomodated by a better language are all those capable of mistake ie all humans.
Rather like the school shooting issue, the C issue is bound up with people at the identity level; they insist on the danger because they cannot stand the possibility of the danger being taken away from them. Their ability to use guns or C safely must not be questioned. They percieve it as an insult to take that choice away from them. They are the safe C programmer that never ships a CVE. They know that they themselves would never shoot up a school, so what the problem? Oh it's bad people. Well, that's happening somewhere else to other people, so it's fine and they can carry on.
Here's an attempt to explaining the irrational part of programmers deciding which programming language to use. Part of it goes into more detail on ideas like C programmers insisting 'on the danger because they cannot stand the possibility of the danger being taken away from them'.
One can in fact not do anything about something for which one refuse to even consider the root causes of.
In the case of shootings, one must talk about what may have caused shootings to start noticeably increasing in around the 1970s, to the point where a single year started having as many shootings as all the shootings prior to the 20th century combined.
Fun fact; the first documented school shooting was perpetrated by some Lenape indigenous people, in Pennsylvania in 1764, during which attack they also beat to death all of the students and scalped everyone.
> Fun fact; the first documented school shooting was perpetrated by some Lenape indigenous people, in Pennsylvania in 1764, during which attack they also beat to death all of the students and scalped everyone
That would probably count under modern definitions of "terrorism". I would also say that most school shootings should also be counted as "terrorism", except there's a very strong ideological push to not look at them this way. Don't look at the radicalisation. Don't read the (suspiciously similar) manifestoes. Don't look at who they cite for inspiration.
If you're going to go back there far, before it was independent, I bet there was something documented in medieval Oxford or Cambridge involving a longbow and/or an anelas.
[Also writing "skill issue" caused me to immediately think of Gill Issue, the Grand Poo World 3 course with a name that's a pun on skill issue, so for anybody else whose brain works the same way, here's somebody competent beating Gill Issue: https://www.youtube.com/shorts/I6PdLgUGHaw ]
>If someone has a choice, a safer more modern language can accommodate less skilled practitioners
The implication here is thoroughly debunked. We’ve seen over and over again that memory safety bugs will happen in every C codebase(ignoring toy or small codebases). Even for the mythical and infallible “skilled practitioner” spending time re-solving the solved issues inherent to C just isn’t a good use of developer time.
> a safer more modern language can accommodate less skilled practitioners.
That’s really what it’s all about. SV is absolutely obsessed with hiring bad programmers, treating them like crap, so they don’t stick around, and somehow, magically, forcing them to write good code.
We have this belief that if we just use the “right” tool (in this case, a particular programming language), all of our products will be good. Couple that, with the belief that we should be able to build our stuff on someone else’s code, for free, and you have a recipe for disaster.
People like Linus Torvalds are living proof that it is quite possible to write amazing stuff, in old languages (he is a C guy), but people like that, are rare as hen’s teeth, and may be difficult for today’s tech managers to handle.
There really is no substitute for running a good shop, hiring good people, training them well, treating them well, paying them well, and keeping them around for significant lengths of time.
Also, we need to be able to hold ourselves accountable for the Quality of our own work -regardless of the tools we use. Torvalds is notorious for being a tough taskmaster, because he’s serious about the Quality of his work, and casts that onto others.
“Treating people well” does not mean using kid gloves. It can mean expecting people to act like grown-ups, produce grown-up work, and not accepting less. I worked in an environment like that for decades. It was often quite stressful, but was also personally rewarding.
It isn’t the tools that are broken; it’s the management culture, and no one wants to fix that.
I have a longer nuanced post to write out at some point about my feelings here, but here's the cliff's notes:
We should not be developing new projects in C, and we should make it politically hard to make new projects written in C in distribution repositories. C is going to stay around for a long time and that's okay, but there are so many inherent problems of its design and implementation that make it unsuited for unsupervised use. I wish that we didn't have to make such hard-line stances about this, but people have continuously proven that this tool is unsuitable for modern development and it's only going to get worse as time goes on.
It's difficult, because "embedded not networked" is an environment where security risks are low, but "embedded networked" is a really nasty environment of haunted routers and abandoned IoT devices.
Is it acceptable to risk buffer overruns on the HTTP server running on an insulin pump?
Well, yes. I'm more focusing on user space applications here. This is why that nuance post would have to be so long. People here would probably misconstrue it to be that I want to "kill C" though. That's part of the reason why I haven't written it yet lol
I agree. I regularly use Rust on embedded devices and what many advocates like to leave out is that you're just using regular old C under the hood anyway. It's bindings all the way down.
Fine, but there's no reason you should be allowed to ship C in devices which have safety critical consequences to the public, including unnecessary risk of data security breaches through allowing buffer overruns. You can write in a nice safe sandbox over there.
(maybe this will eventually be part of the UL/CE requirements, "contains no C code")
C and C++ have another brand of safety "safe" languages du jour don't have: it's an ISO standard. Granted, it's not a very good standard, but the upside is that everyone and their dog has a C compiler for every new architecture, and I bet C++ too. You are not, strictly speaking, beholden to any single compiler implementation out there, they all have their idiosyncrasies, but C won't disappear overnight.
It's more even than having a single foundation oversee it. C and C++ are largely immune to, say, a foundation dissolving because one day it turns out its members cannot comport themselves as responsible adults and a big enough drama ensues. The fact that C and C++ have no singular "community" to speak of is a very strong side.
So when there are at least two (or better three) fully independent implementations of your C alternative, we'll talk about gatekeeping C.
Now, if you are a vendor and capital owner, nothing forbids you from forbidding C within your company and devices you produce. That has been your prerogative since forever, predicated on your ability to afford it. I'm more wound up about activists and evangelists trying to impose their hobby horse upon others. You do you. Show, don't tell.
At some point you just disallow horses to go onto the high-speed road, and aren't waiting for literally every last farmer to sell their horse over a car.
However, if you reduce the language surface it is possible to have something safe and simple enough (IMHO).
For instance, you can say no async, no custom traits and only {Debug, Display, Eq, PartialEq, ...} are allowed for your structs and generics. From limited personal experience that takes away more than half of the complexity of navigating rust code.
The more you take away, the closer you are to a simple but unsafe language. If you remove the "unsafe" keyword, many things you can't solve easily nor optimally.
You might be able to outsource some complexity to external libraries, but integrating libraries is itself a major headache, and it can lead to security issues too.
Fair enough. But unsafe for kernel code I guess it's a necessary evil (that's why I didn't mention it).
However, I believe the being "opt-in" by explicitly marking sections unsafe is the way to go instead of having unsafe by default (which is the only way using C).
It's more than that. Even after you learn it, you will struggle a lot with productivity, especially fast iteration and incremental changes and fixes, as Rust forces you to redesign and refactor your code.
How is that different than learning any other language?
I think Rust’s reputation for being hard to learn is overblown. Yes it is probably a little more esoteric than what you’re familiar with but any decent dev should be able to pick it up
The alternative is jousting with attackers. In production. When you're not aware of it. You're not even on the field, let alone mounted on your horse and wearing armour.
Sacrificing safety might have been defensible on a 40 MHz 80386 that could barely run a C++ compiler (I think this is what I started my career on) but today we find eight-core 3.8 GHz CPUs in desktops and dual-core 1.8 GHz SiPs in wristwatches. Safety should have become table stakes a while ago; Moore's Law already paid for it.
Exactly this. It's all about trade-offs. You need to pick the right tool for the job. Sometimes the right tool is dangerous. Knives are dangerous tools, but you need them if you want to cook a meal.
I love one comparison to hole hawg[0] (used for unix vs windows&mac), which is usable here. Memory safe languages are like a fancy electric drill from target. They get the job done, but if you want some more serious drilling they die on you instead of doing something dangerous. C is like one of those drills which are comprised of engine and a handle (cheap, changeable piece of steel pipe). They are designed to do one thing: they rotate a drill. When drill blocks, they rotate you. But when you take appropriate precautions, boy do it drills...
This is from my favourite book: In the beginning was the command line.
So what are you able to do with C that you can’t do in Rust? Somethings are more difficult to pull off, but everything possible in C is possible in Rust. Worst comes to worst you can always drop into unsafe Rust
This “sometimes you need a knife" argument just doesn’t make sense. You can have the power and the safety. Stop cutting off your fingers.
Make a program for 8051 MCU. Or a lot of other microcontrollers.
> This “sometimes you need a knife" argument just doesn’t make sense. You can have the power and the safety. Stop cutting off your fingers.
Sometimes you need a scalpel.
I'm not against Rust. I still want to start a project where Rust will be worth learning for me, but I'm currently busy writing erlang and java for big systems and C for microcontrollers. This is of course only my local situation, I don't advocate for those languages (I love erlang though and I'm wishing for advertised easy concurrency in Rust, maybe someday).
Actually I’ve been pleasantly surprised by Rust on the Arduino! Things are certainly much easier with the large community behind it, I probably would’ve chosen C if there wasn’t an existing community.
I don’t think Rust should be used everywhere, but I’m firm that it could be used anywhere that C can (short of an unsupported architecture).
This isn't a crazy thought to have about K&R C. They're trying to fit a high level language onto a 1970s computer and so sacrifices must be made. Some of the trades they make are... questionable and others I'd say clearly wrong (they just don't need Tony's billion dollar mistake, nor to be so cavalier with types in general), but it's not as though they're targeting a machine with gigabytes of RAM and a multi-core CPU.
But, people aren't writing K&R C. These days most of them are writing something closer to C99 or C11 and some may be using something newer (e.g. C17) or proprietary (GNU's C dialect) either deliberately or just because it compiled and nobody told them not to.
At that point you've actually given away much of the simplicity, and yet what you get for your trouble is largely more footguns. Trade up for a sound type system and fewer footguns instead.
ISO C comes with a list of constructs that the language is entitled to silently miscompile. Varying from "those bytes can't be an integer, I'll delete that function for you" through "signed integers can't overflow, so that overflow check you wrote must return false, so I'll delete it for you".
This makes simple application code slightly faster. That's kind of a reasonable domain for C++ but on dubious ground for C. Where C is superb is talking to hardware and language implementation, exactly the areas the ISO group has chosen to cripple the language for.
Thankfully compilers know about this and provide fno-strict-aliasing et al. Maybe there should be a std= style flag to change to the language subset that doesn't actively try to miscompile your program chasing benchmark numbers.
What things simplicity do you lose? I think there isn't much of a difference between these dialects. Most important one might be possibility to define variables on the spot instead of at top of block. Then, some people like C99 compound literals. I don't think any of these break simplicity, they are quality-of-life improvements with no interactions with the rest of the language semantics.
Next one is what, the C11 memory model? Doesn't take away any simplicity, just defines things better.
Here's my thinking. It's fair to say C99 isn't that much more complicated than C89, which formalizes various things that are a bad idea such as "volatile", as well as numerous good ideas like hey we should let you define a variable where you use the variable - however C99 adds more of the bad like "restrict".
In both those cases the K&R C model was very simple. You could decide you love how simple this model is, and when smarter compilers optimise it into a pretzel or other languages are faster that's OK. This code used to drive the serial port, now it does nothing, OK, don't use C to write such drivers. This code used to go real fast, now everybody else is faster, OK, don't use C if you need the best performance.
C89 and C99 choose different, making the language more complicated to keep addressing performance and compatibility. In C99 I can write the fast serial port driver, but it's significantly more complicated as a result. The beginner will definitely get it wrong and explaining why is pretty subtle.
Then C11 says actually you're not writing sequential programs, which was a crucial simplification in K&R C - the programs you can write do one thing at a time, in order, and then maybe stop. The memory model in C11 is needed because it says actually your programs might do more or different things at once.
Now, in reality by 2011 lots of people were writing C that's not actually sequential - after all SMP Linux long pre-dates C11. But those weren't legal C programs, they're GNU's dialect and so all bets are off. Nobody is claiming Linux is simple.
So C11 definitely isn't the simple language for a 1970s computer any more. C11 is a competitor with C++ or today Rust. And it doesn't fare so well by that comparison.
So you're focusing on the memory model. To which I'll say, it's not the language but it's the _machines_ that have SMP so effects will be visible out of order. The machines provide you with escape hooks to serialize read and write effects, and the language must give you access to these hooks because if the language opts to keep up the illusion of all sequential effects even in the face of SMP, it has to do so by serializing basically all memory accesses, which is going to be incredibly slow.
That code doesn't appear to be sequential from other threads is not the language's fault. It's just a fact of reality.
If you don't want to do SMP / lock-free programming, you don't have to pay for the complexity. You can still write "sequential programs" like it's K&R. Don't do multiple threads, and you don't have to care. You can also do multiple threads but use mutexes for synchronisation, everything will be fine.
Pretty much nobody uses restrict or volatile. There is some fringe stuff that is obsolete and maybe badly designed, but by and large you don't have to use it or interact with it. Compare this to other languages / ecosystems which have this amount of cruft times 100.
It's still this language where you can define a struct, then define a function that receives a pointer to the struct, and it does as you say, and you can actually read and understand the code a month later.
If you need to go fancy for a reason or another (most likely a bad reason), you can do that too, and of course you'll have to pay for it. But most likely, the complexity is not "cancerous" -- define a simple function interface with the most basic assumptions you require, and the complexity is pretty much isolated behind a simple pointer to an opaque structure.
> So C11 definitely isn't the simple language for a 1970s computer any more. C11 is a competitor with C++ or today Rust. And it doesn't fare so well by that comparison.
"Faster but wrong" isn't really faster it's just wrong.
> That code doesn't appear to be sequential from other threads is not the language's fault. It's just a fact of reality.
What other threads? In a sequential programming language we certainly can't have "other threads".
> You can still write "sequential programs" like it's K&R.
"You can just not use the bits you don't like" is how we got C++ dialects that C++ proponents love to pretend don't exist. If the language is "simple" except for all the new bits that are complicated it's not simple.
With all 3 of these quotes and replies I feel completely misunderstood. I'm not at all trying to say the things that you're contradicting with. Won't engage anymore, but maybe you can reevaluate.
K&R gets used as a shorthand for the "portable assembly" C that some people remember and others swear never existed. That's my guess at what the parent meant, not the syntactic strangeness of writing types after the parameter list.
C11 atomics would have been much better if they'd standardised existing practice instead of inventing something based around the application centric design C++ was inventing. It's nice that there's an acquire/release scheme one can reason with but a real shame that they conflated it with type annotations.
Programs are a lot more complex. The computers aren't.
They were far less homogenous in the early years. Today you have a octet addressed little endian integer machine, with ieee float hardware and a small vector unit. Maybe you have two different instances of that on the same address space, but probably just one.
I think reasonable argument could be made that the complexity in modern computing is primarily self inflicted by software engineers.
My problem with Rust is that it’s a hammer, and every nail is memory safety. If I’m writing a TLS library or kernel module, yes, memory safety is paramount. But if I’m writing pretty much anything else, Rust isn’t worth the slog.
Sorry, should have been clearer. I was thinking in the context of every online discussion I’ve run across around “Rust vs. any other language,” where the diehard Rustaceans insist that we should just rewrite everything in Rust.
Totally agree with you: use the best tool for the job.
What projects need manual memory management? Those where the hardware costs are comparable to development/maintenance costs. That is much rarer than people think.
RAM is cheap, and few applications really need bespoke allocation. And it's not just a question of skill; even the most disciplined make mistakes. It's one of how much brainpower you want to allocate to... memory allocation.
In practice I found C/C++ "manual memory management" fans to know surprisingly little about memory management, or even how much manual memory management costs them in performance.
High end games programming sometimes knocks the love of malloc()/free() (and naive RAII) out of them.
In practice I find malloc()/free() mentioned almost exclusively by GC proponents. I don't know any "manual memory management" fans but only people who think that GC is worse than fully designing a memory management scheme for data-intensive applications. And these people shy away from using malloc(), because it is 1) slow/unpredictable (and yes, slower than GC allocation) 2) A general purpose allocator, which gives us little control 3) requires to match every call with a corresponding free(), which is tedious and error prone.
Note also that with (tracing) GC, you not only pay for the cost of allocation, but also pay for the time your allocated objects live.
Then you have a pretty nice bubble (this is not in jest, I honestly envy you).
A more nuanced take is that I can, in practice, map considerable chunk of developers I met and their understanding of memory as:
"it's magic" > "manual memory management rulz! my C/C++/Rust will be always better than GC" >>> people who actually studied automatic memory management a bit >> people who adjust memory management techniques to specific use cases
The fall off is pretty much exponential in amount of people, which I will admit does make some people defensive thanks to second group being both numerically big and undying because programmers suck at educating new generations. Same can be seen in various other areas, not just GC (though GC links with general trope of "opinions formed from people repeating things learnt from xeroxed half dog eaten copies of notes somewhat relevant on 256kB IBM 5150 PC and Turbo Pascal")
A lot of the time I do encounter people who essentially parrot claims about GC without any understanding of what's happening underneath, and indeed sometimes going about "crazy awesome non-GC solution!" that turns out to call out to whatever malloc()/free() happens to live in libc when I pull the cover and with just as much unpredictability as you can get.
As for paying - allocations in GC systems tend to be blindingly fast, but yes, collection does involve other costs.
What does knowing a lot about memory management look like? Is it like being familiar with heap allocation, the structure of fastbins and co., and some knowledge of lifetime and ownership?
In addition to that, also knowing at least basics (a bit like "classes of algorithms") of automated memory management, memory pooling, understanding and using the knowledge of allocation and mutation patterns in one's program.
A funny story related to all that from one of my previous jobs includes a high performance C++ code base that used forking to utilize preloaded code and data and to easily clean up after itself.
Turned out that naive-ish (even with jemalloc dropped in) memory management in C++ code resulted in latency spikes not because of allocation/freeing, but because they put no control over where things got allocated which resulted in huge TLB and pagetable thrashing as copy-on-write got engaged after forking.
To the point that using something like Ravenbrook's Memory Pool System (a GC) with threads quite possible would let them hit performance targets better.
The lack of memory safety is a property of C implementations, not the language itself. You can have an implementation that reliably crashes on memory errors if you want, though it does get easier if you leave out a few features like casting pointers to ints and back.
There is a multiple decade long history of coaxing a memory safe C embodiment. If it was possible to simply implement memory safety without fundamentally changing the language, you would have a compiler flag that would give to you, requiring no source modifications.
No compiler gives you that memory safety flag (aside from very specific security features, ex. -fstack-protector) because it's not possible in C.
It is totally possible for pointers with bounds checking to exist in C. Turbo C did that 30 years ago. However, why bother trying when whole culture is biased against it and you can use any of the other languages?
I used Turbo C++ (not C) back in the day, and recall near pointers, far pointers, based pointers, but I don't recall bounds-checked pointers. Do you remember any details?
>However, why bother trying
Because it would immediately make the large amounts of C code still in the wild safer for the users, who do care?
For the sake of the example let's assume you make a C to Python compiler/transpiler which uses native Python arrays for every stack or heap based allocation and every pointer arithmetic would be replaced by a checked operation, you'd quite likely get a memory safe language in the 'shellcode impossible unless you really set the program up for it' sense.
This "accommodate less skilled practitioners" you wrote is something that never fails to puzzle me from C/C++ practicing colleagues: the idea that in the problem space there is a high-risk high-reward zone of top performance where only the heroes dare tread.
I am sorry but my observarion is that Nim and LLVM and dare I say even GC-less Java all achieve the same performance as C without the footgun baggage. Sometimes it is good to find a way to move on.
>I am sorry but my observarion is that Nim and LLVM and dare I say even GC-less Java all achieve the same performance as C
This is just false. Sure, they probably are 'close enough', but you can't claim the performance is 'the same' simply because those languages inherently do more to achieve the same results.
C inherently does spend more CPU time on memory management than some GC systems.
The fact that a lot of C/C++ fans do not properly profile those areas of their programs does not mean they do not pay for them.
Or that defensive coding (assuming they do not want to introduce a happy little accident of CVE into the world) is free compared to having compiler lift necessary asserts outside of hot loop.
Some memory-safe languages even provide a faster feedback loop on exact instructions that will be executed for all code you write (probably most famous example is Common Lisp, which mandates that DISASSEMBLE is accessible to developer at all times)
I'm trying to decide if this is a good satirical response to a satirical article? If so, well done!
Because at this point, where can we find programmers who aren't 'less skilled practitioners'? Because it's clear Microsoft, Google, Apple, and major open source projects, have failed to find them based on memory corruption issues in the Linux, Windows and Mac kernels, chrome, and firefox.
[0] https://www.theonion.com/no-way-to-prevent-this-says-only-na...