5 ms·
My Reaction to Dr. Stroustrup’s Recent Memory Safety Comments
- paulrpotts 4y agoGreat article, no notes. I think you are correct about Stroustrup and want to amplify on that a little bit. I will add that I'm in my mid-50s and have been programming since childhood and so I've had a chance to observe the evolution of C++ since the not-quite-C++ implementations such as those in THINK C (Object Extensions to C) and TCL (Think Class Library). I've used quite a few C++ frameworks and libraries that existed pre-STL including Borland's OWL 2.0 and the old Turbo Vision framework, as well as the first version of MFC (Microsoft Foundation Classes - I still have nightmares), and later worked extensively with the massively useful and very nicely designed Metrowerks PowerPlant class library. I used to subscribe to the old C++ Report magazine and read them cover-to-cover. The best of these articles are still available if you can track down old copies of the books _C++ Gems_ and _More C++ Gems_. (One of the fascinating things to be learned from those articles is how practitioners discovered that the exception mechanism in C++ really could only _theoretically_ be made to ensure safe and easy error-handling and recovery, but in practice made it impossible, because the total state of the program and its resources had to be considered at every point in the program in which an exception could occur; at one job, I tried unsuccessfully to convince my co-workers not to use exceptions for error-handling in embedded multi-threaded client/server code in vehicle infotainment devices.) I have owned every edition of Stroustrup's _The C++ Programming Language_ and read his _The Design and Evolution of C++_. I used to buy, print out, and bind, copies of the C and C++ standards so that I could try to answer hard questions about whether compilers were broken, or the code was broken. If I had kept every book I've ever owned on C++ programming, I estimate it would be about 12 feet of shelf space. It is probably a blessing that I have only kept about 2 feet, which now has books on C++17 and C++20 for those times when I have to read some modern C++. At one point (about 1999) I considered myself to be a pretty expert C++ programmer, but because of language churn, those days are gone. (How many times can one re-learn the proper way to write a managed pointer class, or what methods should go into a "standard" kind of class to make it useful and safe? For me, the turning point probably came when I bought a brand new book on STL programming and tried to run the chapter 1 examples. Every compiler I had access to at the time on several platforms crashed when trying to compile the programs, which was a really vivid illustration of just how far the cutting edge was from the reality of working programmers.) I also once went to a talk by Stroustrup on the campus of the University of Michigan, and left frustrated and bored. Given all that, I don't believe Stroustrup's ever been quite the thinker and visionary that some might think he is. He will not be remembered as a great language designer but more a formalizer, implementer, and promoter of ideas mainly borrowed from other languages and other people. He's certainly not a great writer or a great speaker, as I learned at his talk. That itself is not my real criticism of him and his work; there are a lot of great ideas in language design to borrow from. My real criticism of him and his work is that along the way he has not been able to maintain a coherent vision of how language features would work together in real programs. To be fair to him, I think a lot of the people behind incredibly useful and active real-world computer languages such as Guido van Rossum and Yukihiro Matsumoto find themselves in similar positions, but Stroustrup seems to have a particular lack of self-awareness of the limits of his contributions and role in the design and evolution of a language which is now an irredeemable mess filled with too many Ph.D. theses. C++'s metastatic growth began with the early incorporation of Stepanov's Standard Template Library, a very nice design that, initially at least, was grafted into a language not well-suited to implement it. And things have continued from there, with massive, widespread adoption, and many successful projects, but insufficient attention paid to the unsuccessful ones. Meanwhile I have watched so many better languages fail to gain momentum. People choosing languages for implementing important pieces of software would be wise to look at the minority reports of the most experienced engineers - for example, see Torvalds' comments on C++ over the years - rather than the propaganda from the language promoters.
- jeffrallen 4y agoBjorn is probably a nice enough guy. But his opinions as a language designer are negated by the enormous harm done to the industry by C++.
- david2ndaccount 4y agoC++ needs spatial memory safety. It can be added without greatly changing the semantics of the language. Temporal memory safety is much harder.
- deleted 4y ago[deleted]
- olliej 4y agoLibc++ for example is doing just that, it was on HN a while back and generated many many complaints. It doesn’t help though that there’s no way to distinguish a pointer from an array, nor get the length of an array (because you aren’t guaranteed an array is a c++ array with a prefix header or a c style array with a separate size), and given a lot of c++ is still pointers - for example the semantics of iterators makes it hard to be both bounds safe and fast, which means c++ iterators can easily go out of bounds or into random memory in the face of mutation. Now obviously we generally agree mutating something while iterating it is bad, but the c++ iterators semantics makes detecting and stopping that extremely expensive because it’s fundamentally designed around reusing old code that was just incrementing pointers.
- david2ndaccount 4y agoI’m not sure what you mean by “there’s no way to distinguish a pointer from an array”. Arrays and pointers in C and C++ are distinct types, although arrays will decay to a pointer in an expression context (and there is the whole problem with arrays as function parameters being rewritten to pointers which adds to the confusion). C with VLAs can actually express the length of a pointed to array, with the following example: #include <stdio.h> // See the linux kernel for a version that verifies // `x` is actually an array. #define arrlen(x) (sizeof(x)/sizeof(x[0])) void foo(const int x, int(*y)[x]){ printf("%zu\n", arrlen(*y)); } int main(){ int a[3]; foo(arrlen(a), &a); return 0; } If you compile and run the above code, you will see that it correctly prints the length of the array - 3. Unfortunately, the syntax is awkward and most C/C++ programmers would be stumped by the actual syntax for a pointer to an array. There is also no help that the correct length is passed.
- mbfg 4y ago>> While there might be 30+ years of divergence between C and C++, none of C++’s so-called “progress” involved removing memory-unsafe C features from C++, many of which are still in common use, and many of which still make memory safety in C++ near intractible I think just the concept of classes, and new, help with memory safety. It's harder to screw with memory with new Foo() then doing a malloc and memcpying bits into a buffer. Sure it's far cry from real memory safety, but i do think c++ has a bunch of improvements over c in memory safety. Sure you can do all the nasty bits in c++ that you could do in c, but you are carrotted out of doing them most of the time.
- olliej 4y agoAlas it doesn’t really help - new is just as bad as malloc, and the fact that there is no difference syntactically or in the type system between a pointer to an object and a pointer to an array means that c++s new introduces the joy of calling the wrong delete \o/
- david2ndaccount 4y agoThis is incorrect, but most C and C++ programmers would be stumped by `int(*y)[3]` (which is how you spell a pointer to an array of length 3).
- pjmlp 4y agoPlenty of C++ developers still mix up delete versus delete[].
- olliej 4y agoWhich is my point: the type system doesn't distinguish T* (a single object) T* (an array of objects), so delete vs delete[] only shows up as runtime heap corruption that may or may not eagerly terminate or lead to RCE.
- olliej 4y agoThe type of `new T[N]` is T. The type of `new T[10]` is also T. The type of `new T` is also T. Yes if you have a statically sized array you can make a pointer to an array of that length, but those are generally not relevant outside of specific cases (arrays in structs or on the stack where the size impacts offsets in codegen). More over the desire of C and C++ to drop those annotations is such that even using your proposal of a pointer to an array rather than just an array, is of questionable value. Take an extension of your example: int(*y)[3] = ...; int(*y2)[3] = ...; You can't do *y2 = *y; Because C doesn't let you assign arrays by value, even fixed size ones \o/
- gemstones 4y agoSuper interesting article. Is there a word for the type of software architect who pathologically excuses immediate-term problems because there is a fix a long ways away? Dr. Stroustroup's comments sound familiar if you've ever encountered the type of person who won't engage with a problem you have now, because they have a system planned for next year that makes the problem go away.
- gnad_sucks 4y agohttps://en.m.wikipedia.org/wiki/Perfect_is_the_enemy_of_good https://en.m.wikipedia.org/wiki/Perfect_is_the_enemy_of_good
- plaguepilled 4y agoI usually refer to this as "business oriented" - not in a derogatory sense, but because their design decisions are primarily determined by their financial impact, vs another measure (such as fault tolerance, error detection, system consistency, or projected support hours required). A lot of business oriented people may find my delineation here offensive, but it really isn't meant to be. While a business' job is to make money, and employees work for the business, they may still disagree on how to evaluate a given action - because the business making money and being financially optimised may not be the main reason they work there.
- favorited 4y ago> Besides the laughably condescending matter of calling Java (which first appeared in 1995), C# (first appeared in 2000), and Ruby (first appeared in 1995) “novel,” I think "novel" means that they were Greenfield languages. They certainly took concepts from preexisting languages (like Java's "interfaces" being inspired by Objective-C's "protocols"), but they didn't start their lives as "existing-language-with-X," the way C++ was "C, with classes."
- thecodedmessage 4y agoI just don't think this is a remotely justifiable reading.
- voxelghost 4y agoIf user(programmer)-behavior is the main problem, and there is claim to a safe C++ subset, then wouldn't it make sense to implement an UNSAFE compiler attribute macro, to enable the unsafe features, while turning them off in default compilation mode for new versions of C++?
- BearOso 4y agoThere's no unsafe keyword, but most modern C++ people know what is intended to be safe and what isn't, i.e. unique pointers, raii, and bounds-checking accessors. It isn't going to be as strict as Rust, but you get a lot of benefits. Knowing some Rust and how it works, then going back to C++ can help you recognize where to use safer idioms and what's potentially dangerous.
- thecodedmessage 4y agoYou can still have rogue references to deleted objects in such a situation, or invalidated iterators, or plenty of other undefined behaviors even using just modern C++ features.
- voxelghost 4y agoI know there is no unsafe keyword, but I was suggesting one should be added. I am a bit rusty (no pun intended) at the moment, but I have decades-long experience with C++, but not all people do, and all people ,even experienced developers make mistakes or get lazy and take the easy way out from time to time. I think one lesson C++ could take from rust, if nothing else, is that clearly demarking unsafe code sections is beneficial in and of itself. If Strostrup makes the claim that developers using old C features is the main security problem of modern C++ , then an unsafe keyword would guide behavior towards safe usage. #No "old unsafe C" here UNSAFE{ #Full C++, including "old unsafe C" here ... } #No "old unsafe C" here >c++ / treat code as "New Safe C++ only", except for UNSAFE sections >c++ --no-unsafe / treat all code as "New safe C++ only" UNSAFE not allowed >c++ --allow-unsafe / current behavior, allow all C++ including "old unsafe C" in all sections
- garbagecoder 4y agoStroustrup doesn't even mention Rust though and neither does the NSA document he was talking about: "Some examples of memory safe languages are C#, Go, Java, RubyTM, and Swift®."
- steveklabnik 4y ago(The document he refers to has two sections like this, one which mentions Rust and one which does not.)
- garbagecoder 4y agoOK but the post is styled a reply to Straustrup, who doesn't mention it.
- thecodedmessage 4y agoTherefore, what, exactly? Do you think Stroustrup is not aware of Rust? Do you seriously think he wasn't thinking about Rust when he wrote this? Even if he wasn't, don't you think he should've been? Do you not think the existence of Rust is relevant to the conversation? Is this discourse bound by some lawyer-like rules where if someone doesn't bring up something that everyone knows is relevant, it's off the table to mention? Should I have filed a form with you asking for permission to bring up a topic not mentioned in the document I was responding to, even though everyone thinking through it with good faith knows it's on topic?
- garbagecoder 4y ago>Do you seriously think he wasn't thinking about Rust when he wrote this? If he was, then why didn't he mention it? You seem to know what Stroustrup's inner thoughts are, so tell me, why didn't he mention it? Maybe he wants to avoid the ten million reply guy Rust evangelists out there (ahem), maybe he doesn't think it's relevant to the discussion for other reasons. Please enlighten me. Obviously, anyone can blog about anything they want to but likewise I can ask questions too. You seem very upset that I asked such a simple question. You might have heard of this phenomenon called "click bait" where people inject themselves into only very tangential discussions to get clicks. Or, in this case, I suspect to preach to the choir. Now, let me ask you: do you have an opinion about what Stroustrup wrote or are you just making sure no one says anything bad about [your_favorite_lang].
- meitros 4y agoIs the opt-in versus opt-out point at the end of the article really important? Even if the compiler is opt-in you could use a separate tool to enforce preventing unsafe memory idiom usages unless annotated (akin to linters from other languages), and C++ codebases don't tend to have the same sprawling uses of third-party libraries that other languages do.
- Ygg2 4y agoYes? An ounce of prevention is worth a pound of cure. See Yaml safe load vs load. Since default method is unsafe due to Yaml bugs there were wide ranging consequence across most of ecosystem. If default was safe load, and you could opt-in to features of Yaml that caused unsafety it would be a much lesser problem.
- rfdonnelly 4y agoYes. Defaults matter. Here's one example https://blogs.iadb.org/ideas-matter/en/organ-donation-changing-default-can-save-lives https://blogs.iadb.org/ideas-matter/en/organ-donation-changi....