> With POSIX semaphores, mutexes, and shared pointers, it is very rare to hit upon a memory issue in modern C++.
There is a mountain of evidence (two examples follow) that this is not true. Roughly two-thirds of serious security bugs in large C++ products are still memory-safety violations.
I write high performance backends in C++. Works approximately as described in article and all data are in RAM and in structures specialized for access patterns. Works like a charm and runs 24x7 without a trace of problem.
I've never had a single complaint from my customers. Well I do have bugs in logic during development but those are found and eliminated after testing. And every new backend I do I base on already battle tested C++ foundation code. Why FFS would I ever want to change it (rewrite in Rust). As a language Rust has way less features that I am accustomed to use and this safety of Rust does not provide me any business benefits. It is quite the opposite. I would just lose time, money and still have those same logical bugs to iron out.
How many other programmers have you trained up to that level of results? Can you get them to work on Windows, Chrome, etc. so users stop getting exposed to bugs which are common in C-like languages but not memory-safe languages?
I do not train programmers. I hire subcontractors when I need help. They're all same level as myself or better. Easy to find amongst East Europeans and does not cost much. Actually cheaper than some mediocre programmer from North America who can only program using single language / framework and has no clue about architecture and how various things work together in general.
Any reasonable meaning of “proper” would include not causing memory issues, so you’ve just defined away any problems. Note that this is substantially different from not having any problems.
The great lesson in software security of the past few decades is that you can’t just document “proper usage,” declare all other usage to be the programmer’s fault, and achieve anything close to secure software. You must have systems that either disallow unsafe constructs (e.g. rust preventing references from escaping at compile time) or can handle “improper usage” without allowing it to become a security vulnerability (e.g. sandboxing).
Correctly use your concurrency primitives and you won’t have thread safety bugs, hooray! And when was the last time you found a bug in C-family code caused by someone who didn’t correctly use concurrency primitives because the programmer incorrectly believed that a certain piece of mutable data would only be accessed on a single thread? I’ll give you my answer: it was yesterday. Quite likely the only reason it’s not today is because I have the day off.
> And when was the last time you found a bug in C-family code caused by someone who didn’t correctly use concurrency primitives because the programmer incorrectly believed that a certain piece of mutable data would only be accessed on a single thread? I’ll give you my answer: it was yesterday.
You answered my question. My original argument was using concurrency primitives "properly" in C++ prevents memory issues and Rust isn't strictly necessary.
I have nothing against Rust. I will use it when they freeze the language and publish a ISO spec and multiple compilers are available.
> My original argument was using concurrency primitives "properly" in C++ prevents memory issues
Yes, I know, I addressed that. It's true by definition, and a useless statement. Improper usage will happen. If improper usage results in security vulnerabilities, that means you will have security vulnerabilities.
Note that I say this as someone who makes a very good living writing C++ and has only dabbled in rust. I like C++ and it can be a good tool, but we must be clear-eyed about its downsides. "It's safe if you write correct code" is a longer way to say "it's unsafe."
You're right, if you use the concurrency primitives properly you won't have data races. But the issue is when people don't use the concurrency primitives properly, which there is ample evidence for (posted in this thread) happening all the time.
But with this argument, the response is "well they didn't use the primitives properly so the problem is them", which shifts the blame onto the developer and away from the tools which are too easy to silently misuse.
This also ignores memory safety issues that aren't data races, like buffer overflows, UAF, etc.
Proper usage is fine. The problem is that it is easy to make mistakes. The compiler won't tell you and you may not notice until too late in production, and it will take forever to debug.
Here's two: CVE-2021-33574, CVE-2023-6705. The former had to be fixed in glibc, illustrating that proper usage of POSIX concurrency primitives does nothing when the rest of the ecosystem is a minefield of memory safety issues. There are some good citations on page 6 of this NSA Software Memory Safety overview in case you're interested://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF
There is a mountain of evidence (two examples follow) that this is not true. Roughly two-thirds of serious security bugs in large C++ products are still memory-safety violations.
(1) https://msrc.microsoft.com/blog/2019/07/we-need-a-safer-syst... (2) https://www.chromium.org/Home/chromium-security/memory-safet...