A personal opinion from a person who loved C++ for quite some time, before diving deep enough to realize how dark is the abyss.
Anybody who has the faintest clue about both languages should know that.
It's undefined behavior, despite not calling free anywhere. Replace with std::string and it could be use after free. In C, UAF wouldn't happen that silently for heap memory.
From my POV compilers should warn that this code is potentially dangerous. My rule is: never return a reference or pointer from a function to something whose lifetime you don't have control of.
With C++, good luck even reading and understanding The ISO C++ Standard. Not to say fully internalizing all possible interactions between all nuances. I presume not all of them may even be truly 100% fully fleshed out and explored in The Book. As to writing a compiler - even just writing a parser for C++ is famously super hard!
Anyone that is able to keep in mind the documented 200 cases of UB is my hero.
> Writing C++ code longer than a few lines without UB is humanly impossible.
Do you want me to provide one for you? Because that will definitely change your definition of 'humanly impossible' tasks and might also bring you back from realms of using comically bad phrases..
Please note I didn't say a word about Rust here :) That's your overinterpretation. First of all, I never actually used Rust; from what I've seen, I feel it has some potential and good ideas; but OTOH, I also get the feeling that one is forced to use 'unsafe' blocks from time to time anyway, so there's still some area for self-inflicted danger. Even standard library has some errors found from time to time and reaching the news. Also the compiler is new so not very much battle proven yet. Also I'm somewhat uneasy about the fact, that Rust seems to be quite a big language already, and still growing in complexity. Not sure what's the solution. But C++, as it is now, in my opinion is most certainly not one.
I was employed in a big corporation and working on a moderately big C++ codebase. It totally had UB, overwriting random memory, exceptions, etc. It was common knowledge in the operations that the app crashes randomly lots of times a day and has to be restarted automatically, to the point of this being considered non-issue. Virtual inheritance was avoided; don't recall non-public. Pointers to members, suppose yes. Templates - oh, tons of them, and growing. The company actually has super smart C++ programmers (and I mean it!), submitting proposals to the C++ committee and having them accepted. Now, note the Brian Kernighan's quote about debugging clever code. I once debugged a somewhat more -often-than-normal crash. It ended up proving to be a data race. It was a fun experience, though at times totally depressing. UBs were so common during this debugging that I simply ignored them, or I'd go insane. But when I look at how easy it is to detect and debug races in Go, and how still I have to be careful to avoid races there, and still make them from time to time, I know there are tons of them sleeping undetected in any multithreaded C++ code. And we had valgrind etc (though it was rarely used, as it slowed the app to a crawl). Now, all the perfect "modern" or "subset" C++ you claim is so flawless (for whatever actual definition of "modern" you'd try to choose) is never fully enforceable, because it would be too strict or "not performant". Plain ugly non-modern C++ will spill, I don't believe you'll avoid it in any corporate environment. Maybe in an idealized open-source side project, in theory.
As to rm, bash, zsh, Windows Explorer's right click, etc - I'm sure they are broken! Those are the so called "bugs" you hear about so often. I didn't once say I won't use those tools. I only wish they weren't so buggy and unreliable... On the other hand, worth to note that there's always a random cosmic ray from time to time, or a bug in processor's microcode. So even Rust or Idris may not protect you at all time, I suppose plain old asserts may be more reliable as a last line of defence.
And back to your first point: again, "you have to delete ASAP" is a strawman from you here. But anyway, Windows totally has tons of security bugs, see all the NSA exploits, recent ransomware, Pwn2Own, etc. Though they seem to have gradually learned since the Win95 and XP days and stuff is slowly improving. Linux, absolutely has bugs and security holes! Linus is famously not treating security holes as serious bugs, isn't he. Filesystems are buggy as hell! SQL database engines have to go to great lengths to try guaranteeing atomicity and reliability of writes over existing filesystems. Drivers, woohoo, those are especially famous for being buggy and of low quality standards, on whatever OS you like. But I never said to not use them. But you can't stop me from wishing and hoping we have them safer and more reliable some day. And maybe hopefully helping to do that too. Stuff like OpenRISC, seL4, GenodeOS (C++! that part makes me uneasy actually, unfortunately), Nix (again C++), maybe even QubesOS, give me some glimmer of hope for a more reliable future.
Most fundamentally, that's a corporate culture issue. That should not be regarded as normal in any sane environment. (And, yes, such environments do exist.)
> The company actually has super smart C++ programmers (and I mean it!), submitting proposals to the C++ committee and having them accepted.
But not thinking it's a problem when the app crashed multiple times a day? That sounds like architecture astronauts, not good programmers.
> I know there are tons of them [data races] sleeping undetected in any multithreaded C++ code.
No. I've worked on real-time multithreaded code that had no data races, thanks to judicious use of mutexes. (Now, I can't prove that, and you could argue that they're there, and I just don't know it.)
It's possible to do much better with C++ than what you experienced - to write solid stuff that doesn't crash every day, still less multiple times a day; to write multithreaded code that isn't riddle with race conditions; and so on. Mostly, what it takes is a team (or corporate) culture that insists on quality code, from start to finish - good design, good development, good testing and debugging.
I'm sure you have seen BS codebases in Java, C#, PHP, Python, etc. as well, I've seen weird interactions with GC in WildFly (I can't comment more because I'm not a Java programmer), spooky action at a distance, globals, using one huge table in a DB to store everything thus missing the point of a relational DB, etc. all in non C nor C++ and it'd not help these things if they were in Rust.
Not all bugs come from the language itself either, some are just true programmer errors. I just google for PHP SQL tutorial (not an English one) and the result is of course pasting input together with SQL to form a query, 0 escaping... Sony had a leak like that. Many Windows issues are pure ignorance like having SMB (that turned out to be buggy, but still) running by default, similarly stuff like misconfiguration, default passwords, Apple's goto fail won't be solved if people are copy pasting code and formatting it badly (unless Rust enforces that, I'm not sure, I don't know Rust yet). Rust will not prevent these kinds of mistakes (maybe the last one if the compiler itself detect inaccessible code and maaybe the SQL one if it marks the variable from user input unsafe at first and cascades that through the function calls to see if it was pasted and passed to SQL) unless it has extremely deep understanding of what's going on.
Additionally, despite all the bugs in Windows there (sadly) wasn't a huge exodus to Linux (which too has tons of bugs and is in C and has lots of programs in C++), it just works "well enough" despite the flaws, there no disaster hanging over our heads.
Why the sarcasm?
Use after frees and numerous other memory bugs are discovered all the time in C/C++ programs (including kernels and browsers). This isn't an imaginary problem. Then combine multithreading and you've got a whole extra level of possible issues. Rust does solve many of these problems, and you can prove it does so mathematically.
I understand why people don't like the use of the term "safe" because it feels like a value judgement. But I think people's egos really should be a bit less fragile when discussing language choices.
> Then just delete your entire OS or at least your browser, don't force yourself to use C and C++ software.
With RedoxOS you actually could do that in the near future once it supports some more hardware. The kernel and entire userland (with graphics) is written in Rust. And they did it in 2 years. If nothing else you have to admit that there are some very talented engineers using Rust.
Mathematical provability and technical excellence has sadly little to do with adoption - see where JavaScript, Erlang, Haskell, OCalm, Modula, etc. ended up and tell me every language got what it deserved based on its own merit.
Fanboying over Rust and RedoxOS (it being impressive or not is besides the point) won't fix all that "doable if stars align C" and "humanly impossible C++ that has UB even after few lines" code out there in the government, power plants (including nuclear), infrastructure, stores, embedded, banks, ...
Egos have nothing to do with it. I dislike JavaScript, Java and C# personally (not for any technical reasons but due to my tastes) but if I've seen someone saying the are useless and everything written in them is broken I'd call BS. I'm similarly fond of Free Pascal with LCL for personal GUI toys but if someone said it'll take over the world and destroy Qt and GTK+ behemoths I'd also call BS. Hell, I'd defend your precious little Rust if someone said something stupid about it.
There's factual critique (which I have lots of myself and I don't recommend C or C++ to new hobbyist programmers but Python3), there's personal taste (that you mustn't camouflage as technical opinions) and then there's pedal to the metal "I hate the language so it's totally useless and no human can use it" BS like the OP's comment.
Rust supposedly targets C and C++ programmers so it shouldn't be acceptable to shit all over their tools and by extension their work, telling them they are stupid for liking these languages and are doing everything wrong as an engineer. The fact that such BS is disallowed in official Rust spaces is really telling of how idiotic and ridiculous it is: https://news.ycombinator.com/item?id=14755394
I'm not saying C++ kills people. But I am saying it is producing inherently buggy software, on some level. I'd say it this way: improvements that Rust, Idris, Haskell & many other new languages (and also some old ones, actually, like reportedly Modula, Ada, etc.) try to bring to the table, are similar to what procedural programming or type systems brought over assembly. Resisting those improvements is... strange to me.
[edit: I noticed I wasn't allowed to reply to some comments downstream a while before. I think this may be some kind of a signal for me to just STFU and drop the ball; even if not, I decide to just treat it so, I've said more than enough words already probably. Actually, biggest outburst of my posts on HN ever. I'm starting to think I might be having some kind of a PTSD w.r.t. C++. Anyone knows of some good therapy centers for recovering C++ veterans? :) ]
For exmaple, in C++, we can put two strings together to make a new string without worrying about whether we have a buffer large enough to hold the result, and whether null termination is ensured and so on, or whether or not the original source strings are damaged in the process (they are not), or whether that memory will disappear when we return to the caller. It's just str1 + str2.
I'm no C++ advocate, bu the fact is C++ code can look like a scripting language and be safe like one. C++ also has tools for isolating and managing the C-like semantics that a C++ program might contain.
So even to clump together C and C++ as "C/C++" is not well considered. There isn't a "C/C++" language. If you post a message about C/C++ in the comp.lang.c newsgroup, put on your flame-proof asbestos underwear first.
For instance, erasing from some containers causes undefined behavior if iterators that were created before the deletion continue to be used.
Some of the various smart pointers for managing memory are not so smart; they have been redesigning new ones and deprecating old ones so many times now. It used to be "your code isn't exception safe: use auto_ptr, you dolt!". Then, "you idiot, don't use auto_ptr, use this instead" and so on.
You can avoid all that by defining your own classes that do just what you need, use only the safe stuff from the standard (like the aforementioned strings) and write yourself a perfectly memory-safe, leak-free C++ program.
The "you (and the standard library, including the completely new parts) are holding it wrong" defence is tired, when it is so ridiculously easy to do so: it is okay and important to acknowledge that a tool is powerful but also has a pile of hard-to-avoid sharp edges.
This is specially the case in the majority of enterprise software that doesn't use any kind of static validation tooling, or CI builds.
If you can't enforce that certain rules be enforced in a C++ program, you also can't enforce that someone won't sneak C++ modules into a code base written in another, safer language.
> doesn't use any kind of static validation tooling, or CI build
Or, also: a review tool for rejecting stuff that is against the project's explicit coding guidelines.
In Java and .NET projects you can easily ensure that, and that is a common scenario in some of our customers.
The machines are provided locked down by IT with the project sanctioned tools, including the configuration for in-house Maven and NuGET repositories.
No native code compiler gets installed, servers are configured to disallow unsafe code.
Any library not available requires a change request to the IT team.
Stuff you don't want in C++ code can be rejected by a pre-commit hook which scans code. That header can't be #include-ed, that crazy operator can't be used, etc.
Also, with open source compilers, you can implement your own warnings. (Been there, done that; in the role of an embedded distro/kernel/toolchain person some years ago, I hacked g++ with custom warnings).
If there is something we don't want in C++, and it doesn't "grep" well, we may be able to diagnose its presence in the compiler and treat that as an error.
This is why on Solaris there is OS support via SPARC instructions to enforce bounds and valid pointer use, for example.
You made C++ sound as bad as Java applets or something similar. Obviously anyone saying Java applets are unsafe, bad, etc. is telling you between the verses to not run any, ever. The words you used were very strong and made it sound like everything is buggy as hell while the bugs are minor and few and far between (relatively speaking, there are lots in some places but your browser and OS is not crashing or leaking your data to hackers on a daily basis, the situation is nowhere near tragic).
Saying C and C++ are unsafe basically shitted on every programmer ever that picked them for anything important, kernel makers, browser makers, server makers, languages VM makers - all idiots, endangering people and property, writing unsafe software!
I mean, seriously, understanding the borrow checker is nowhere near as hard as understanding this: https://akrzemi1.wordpress.com/2013/10/10/too-perfect-forwar...
There's a No True Scotsman aspect to C++ advocacy. Anything that is obviously dumb either is because the programmer did it wrong, because it belongs to the ever-growing list of features you avoid or "doesn't come up that often".
(no true Scotsman)
What do you call modern C?
"We found a terrifying vulnerability in your codebase. You should rewrite it in modern C++."
"OK, done!"
<Time passes>
"We found a terrifying vulnerability in your codebase. It must not have been modern C++!"