points by clnq 3 years ago

Programming languages are tools for a job. As the saying goes, a bad workman blames his tools. It's not worth taking anyone who blames defects on a programming language too seriously, whether it's Google or not.

Modern C++ has many memory safety features. If a company has learned that its people fail to use them, then bad for them.

Of course, there are languages that abstract memory safety to the point that they eliminate those types of mistakes. But languages are tools for a job, and only some tools are applicable where C++ is applicable. We should not bury C++ prematurely before answering the question - "what else is as fast and efficient as to replace it for OOP?" And if a project doesn't need fast and efficient code, then why is it using C or C++ in the first place?

Overall, selecting the correct tool for a job is more important than figuring out which tool is better in some abstract way.

Tuna-Fish 3 years ago

> As the saying goes, a bad workman blames his tools. It's not worth taking anyone who blames defects on a programming language too seriously

Are you serious? A bad workman blames his tools, because workmen are reponsible for their tools. A large part of being a good workman is identifying what tools are good and using them.

And C++ is a terrible tool for any task where you are not forced to use it because of existing libraries. All the memory safety features of modern C++ are a tiny, almost vanishingly small step in the right direction.

> "what else is as fast and efficient as to replace it for OOP?" And if a project doesn't need fast and efficient code, then why is it using C or C++ in the first place?

If you need fast and efficient code, why on earth would you be doing OOP?

  • clnq 3 years ago

    > A bad workman blames his tools, because workmen are reponsible for their tools. A large part of being a good workman is identifying what tools are good and using them.

    As I said in the comment to which you are responding, "selecting the correct tool for a job is more important than figuring out which tool is better in some abstract way."

    > C++ is a terrible tool for any task where you are not forced to use it

    Many game developers, OS developers, and massive hardware-software makers doing embedded programming who use C++ would disagree. What would you say to them?

    > If you need fast and efficient code, why on earth would you be doing OOP?

    For small projects, I could agree. What would your recommended alternative be for massive codebases in large tech companies that need fast and efficient code?

    P.S. Please read https://news.ycombinator.com/newsguidelines.html about snarky comments. Thanks.

    • pizza234 3 years ago

      > For small projects, I could agree. What would your recommended alternative be for massive codebases in large tech companies that need fast and efficient code?

      The poster wrote very clearly:

      > where you are not forced to use it

      If one is forced, there's obviously no option.

      The idea is not that C/C++ should be replaced right now, rather, that devs finally understand that C/C++ should not be used where possible.

      I actually see this pattern used by some, who defend C/++: "C/++" should be deprecated" - "No, it's impossible to eliminate C/++ today".

      Deprecation is not elimination. Linux started introducing it, and Google is doing as well, so it can be done gradually.

  • ilyt 3 years ago

    >> As the saying goes, a bad workman blames his tools. It's not worth taking anyone who blames defects on a programming language too seriously

    >Are you serious? A bad workman blames his tools, because workmen are reponsible for their tools. A large part of being a good workman is identifying what tools are good and using them.

    Also C/C++ made into real life tools would be OHSA violation on OHSA violation in real world

mamcx 3 years ago

> As the saying goes, a bad workman blames his tools.

And a good workman put his old/obsolete/dangerous/etc tool behind when something better show up.

The bad workman, instead, continue blaming his tools, when the problem is that he CONTINUE using bad tools, anyway!.

P.D: I learn about mechanical engineering. Get rid of bad tools fast is like key around that...

  • ilyt 3 years ago

    First rule of tool buying, never buy the cheapest for the safety-related tools. C/C++ IS the cheapest

tptacek 3 years ago

Modern C++ has many memory safety features. If a company has learned that its people fail to use them, then bad for them.

This recapitulates an argument at least as old as C89. You can probably find Usenet posts deploying it to argue against the adoption of strncpy, because if people don't know how to use sizeof and strlen, then bad for them.

  • saagarjha 3 years ago

    strncpy is bad for other reasons, mind you.

  • clnq 3 years ago

    Yes, my argument sounds similar. But it's in support of modernity rather than primitivism.

    C++ nowadays can be used in a very memory-safe way without much effort. In my professional experience, memory leaks and corruptions are sporadic in modern C++ code and common in old-style pre-C++ 11 code.

    That's why I'm a bit skeptical of this article from Google. It seems reasonable that Android has quite a lot of pre-C++ 11 code. And the article seems to lump two very different approaches to memory safety in pre and post-C++ 11 style programming.

    • raggi 3 years ago

      You can do some basic analysis about your assumption: go pick out a bunch of the CVEs and look at the age and style of the source code.

      Another approximation is to look at the Android source tree to see what proportion of it is as old as you assume in your argument. There are 431 results for a search `"Copyright 200" filepath:.\.cpp`. There are 7465 results for `"Copyright 201" filepath:.\.cpp`. 4152 results for `"Copyright 202" filepath:.\.cpp`. 220 for 2012, 354 for 2011. If you exclude tests the ratio is even less favorable for your theory.

      In case you're wondering the project policy is to add a copyright header at the time the file is created, they do not update years in headers arbitrarily. As a spot check the first file matching "Copyright 200" that wasn't just essentially C code wrapped in extern "C" was: external/angle/src/libANGLE/Config.cpp. This file contains the use of std::make_pair.

      You can perform these searches yourself here: https://cs.android.com/search?q=%22Copyright%20200%22%20file...</i>

      • clnq 3 years ago

        Thanks, that was very insightful. Yes, as you say, the copyright year in a .cpp/.h doesn't necessarily say whether C++ 11 features are used.

        I've looked at many "Copyright 201" and "Copyright 202" headers. I needed to see more use of C++ 11 or equivalent smart pointers or containers to say that this codebase uses modern C++ memory safety features. Other modern C++ features (like std::make_pair that you mention) are easier to spot.

        I expect this codebase to have many memory safety issues. It may not pass code review in a company/team that expects their people to use modern C++ memory safety features. After seeing it, I'm more convinced that the reason Google has so many problems with C++ in Android really is because they don't insist their engineers use modern C++ (or equivalent in-house containers/pointers).

        Here's another insightful pair of searches:

        " std::make_" filepath:.*\.cpp

        "delete " filepath:.*\.cpp

        • humanrebar 3 years ago

          I mentioned this elsewhere, but the real A/B test here would be to do a rewrite in the existing language and compare it to doing a rewrite in Rust with respect to memory safety, etc.

        • UncleMeat 3 years ago

          "std::make_" isn't a great comparison (IMO) because Google has a widespread culture of noexcept so it wasn't critical to adopt this style for constructing smart pointers. std::unique_ptr<Foo>(new Foo()) was a thing for a while there. There is also an alternative absl::MakeUnique<T> that was available before we had std::make_unique available internally so you'll need to search for that too.

          The style guide, C++ readability, and general code review has all but banned raw "new" for years and years. You can find plenty of CVEs where the root cause is a UAF on a managed object.

          • clnq 3 years ago

            Yes, there are more examples of smart pointer initialization than just std::make_. I couldn't find instances of "absl::Make" in Android Code Search. But your point still stands, and I should add that not all new-delete pairs are evil. With that said, what I've seen still has too many raw pointers.

            Thanks for the context about UAF. I am curious about this. Much of my C++ experience comes from working with in-house reimplementations of std/stl, so my question might be a bit stupid, but how is use after freed of an obj managed by smart pointers so prevalent? Should the smart pointer not be nulled after the object is destroyed? Maybe you have a good example CVE? Are these cases of using the raw pointer in the smart pointer without checking it first?

            • UncleMeat 3 years ago

              > Should the smart pointer not be nulled after the object is destroyed?

              I'm not sure what you are going for here.

              The way this often happens is there is some module that owns an object with a unique_ptr and references to that object are used elsewhere. But the ownership of the object is complicated so a bug sneaks in where a non-owning reference to the object gets dereferenced after the unique_ptr is deleted. You can prevent this by having literally everything use shared_ptr for everything but that sucks for lots of reasons.

              • clnq 3 years ago

                There are also other smart pointers, like std::'s weak ptr and proprietary stuff.

                You can avoid multi-ownership problems of shared ptrs with weak pointer member variables (which only need to be turned into shared in a given {} scope). Some other problems can be solved by marking objects as pending kill without destroying them immediately and ensuring all threads finish access before actual deletion.

                Unreal Engine uses both weak pointers and object marking in a global object array. It also uses GC but that's besides the point.

                Would the same approach to modern memory management not help Android?

                • UncleMeat 3 years ago

                  Of course there are designs that help prevent bugs. Chrome is doing plenty of stuff like this but the ownership and lifetime design for something like a JIT are complex as hell and problems happen.

                  We've got like 30 years of people insisting that it really is possible to write safe C and C++ programs if you just follow the One True Way (TM) and its never been the case. Each new One True Way helps, but it sure as hell doesn't solve the problem altogether.

  • jstimpfle 3 years ago

    strncpy doesn't do what you want. Maybe you mean snprintf. Indeed use of sizeof, memcpy, and snprintf. Avoid strlen, it is rarely necessary.

raggi 3 years ago

> We should not bury C++ prematurely before answering the question - "what else is as fast and efficient as to replace it for OOP?"

We have an answer: Rust. It's no longer premature, bury it.

  • j16sdiz 3 years ago

    Rust is over engineered in some area, immature in other.

    See how many reference types are there, how async is handled and the underspecified unsafe semantic.

    For higher level tasks, I prefer a language with GC like go or java. Rust can work with references counting, but it don’t mix well with the larger ecosystem. For lower level task, the underspecified unsafe model make it worse than C aliasing problem

    • unrealhoang 3 years ago

      > See how many reference types are there,

      2, & and &mut. What else?

      • kaba0 3 years ago

        I guess parent meant ARC, RC, and the like.

    • ilyt 3 years ago

      I vastly prefer "just write you code serially and never worry about async then spawn 10000 goroutines" approach over async/await/Future nexus of bad ideas (just do message passing like Erlang or don't do it at all...), but I wouldn't use Go in place where I'd use Rust and vice versa, they kinda feel different (if overlapping in places) niche

      • lanstin 3 years ago

        It is very freeing. And one concise readable go routine doing the channel reads and the socket ops becomes your connection pool, but is as easy to understand as a Network programming 101 assignment.

  • verdagon 3 years ago

    How's Rust at doing OOP these days? (Assuming we're in a domain or situation where OOP is a good choice, of course.)

    I would love to know about any projects that do OOP well in Rust.

    • nicoburns 3 years ago

      IMO Rust has most of the best bits of OOP (the ability to encapsulate functionality in an object with private fields and present a restricted public interface), without the bad bits (inheritance, and complex soups of objects all holding pointers to each other that make code flow hard to reason about)

  • HideousKojima 3 years ago

    Rust isn't OOP though. Structs, traits, etc. let you approximate some aspects of OOP, but not much more than plain old C does.

3836293648 3 years ago

A bad workman may blame his tools, but a good workman uses the right tool for the job. If a better tool exists, use it.

(And sure, it doesn't apply to every niche yet, but it sure applies to a lot of them)

hardware2win 3 years ago

Languages encourage or prevent its users from doing things

Concepts like sugar syntax and syntax salt do exist

Approaches to problems may vary by languages because lang environment shapes its users in some ways